Pandas có thể vẽ biểu đồ ngày tháng không?


100

Tôi đã lấy Chuỗi của mình và ép buộc nó vào cột ngày giờ của dtype = datetime64[ns](mặc dù chỉ cần độ phân giải theo ngày ... không chắc chắn cách thay đổi).

import pandas as pd
df = pd.read_csv('somefile.csv')
column = df['date']
column = pd.to_datetime(column, coerce=True)

nhưng âm mưu không hoạt động:

ipdb> column.plot(kind='hist')
*** TypeError: ufunc add cannot use operands with types dtype('<M8[ns]') and dtype('float64')

Tôi muốn vẽ một biểu đồ chỉ hiển thị số ngày theo tuần, tháng hoặc năm .

Chắc chắn có một cách để làm điều này trong pandas?


2
bạn có thể hiển thị một mẫu của df bạn có?
jrjc

Câu trả lời:


164

Với df này:

        date
0 2001-08-10
1 2002-08-31
2 2003-08-29
3 2006-06-21
4 2002-03-27
5 2003-07-14
6 2004-06-15
7 2003-08-14
8 2003-07-29

và, nếu nó chưa phải là trường hợp:

df["date"] = df["date"].astype("datetime64")

Để hiển thị số ngày theo tháng:

df.groupby(df["date"].dt.month).count().plot(kind="bar")

.dt cho phép bạn truy cập các thuộc tính datetime.

Cái nào sẽ cung cấp cho bạn:

nhóm theo ngày tháng

Bạn có thể thay thế tháng theo năm, ngày, v.v.

Ví dụ, nếu bạn muốn phân biệt năm và tháng, chỉ cần thực hiện:

df.groupby([df["date"].dt.year, df["date"].dt.month]).count().plot(kind="bar")

Cái nào mang lại:

nhóm theo ngày tháng năm

Nó có phải là những gì bạn muốn? Điều này có rõ ràng không?

Hi vọng điêu nay co ich !


1
Nếu bạn có dữ liệu kéo dài trong vài năm, tất cả dữ liệu 'tháng Giêng' sẽ được đưa vào cùng một cột và cứ tiếp tục như vậy cho mỗi tháng.
drevicko

Hoạt động, nhưng đối với tôi (gấu trúc 0.15.2) ngày phải được viết hoa D: df.groupby (df.Date.dt.month) .count (). Plot (kind = "bar")
harbun

@drevicko: Tôi tin điều đó. @harbun: datehay Dateđây là tên cột, vì vậy nếu cột của bạn với số ngày được gọi là foo, nó sẽ là:df.foo.dt.month
jrjc

@jeanrjc Nhìn lại câu hỏi, tôi đoán bạn đúng. Đối với những người khác như tôi, những người cũng cần phân biệt theo năm, có cách nào đơn giản để groupbykết hợp hai thuộc tính của dữ liệu cột (ví dụ: năm và ngày) không?
drevicko

Có cách nào để chuẩn bị ngày tháng để tôi có thể sử dụng seaborn.distplot () để vẽ biểu đồ lịch sử theo ngày không?
panc

11

Tôi nghĩ rằng resample có thể là những gì bạn đang tìm kiếm. Trong trường hợp của bạn, hãy làm:

df.set_index('date', inplace=True)
# for '1M' for 1 month; '1W' for 1 week; check documentation on offset alias
df.resample('1M', how='count')

Nó chỉ thực hiện đếm chứ không phải thực hiện âm mưu, vì vậy bạn phải thực hiện các âm mưu của riêng mình.

Xem bài đăng này để biết thêm chi tiết về tài liệu của tài liệu lấy mẫu lại gấu trúc

Tôi đã gặp phải những vấn đề tương tự như bạn đã làm. Hi vọng điêu nay co ich.


2
howkhông được dùng nữa. Cú pháp mới làdf.resample('1M').count()
Dan Weaver

6

Kết xuất ví dụ

nhập mô tả hình ảnh ở đây

Mã mẫu

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Create random datetime object."""

# core modules
from datetime import datetime
import random

# 3rd party modules
import pandas as pd
import matplotlib.pyplot as plt


def visualize(df, column_name='start_date', color='#494949', title=''):
    """
    Visualize a dataframe with a date column.

    Parameters
    ----------
    df : Pandas dataframe
    column_name : str
        Column to visualize
    color : str
    title : str
    """
    plt.figure(figsize=(20, 10))
    ax = (df[column_name].groupby(df[column_name].dt.hour)
                         .count()).plot(kind="bar", color=color)
    ax.set_facecolor('#eeeeee')
    ax.set_xlabel("hour of the day")
    ax.set_ylabel("count")
    ax.set_title(title)
    plt.show()


def create_random_datetime(from_date, to_date, rand_type='uniform'):
    """
    Create random date within timeframe.

    Parameters
    ----------
    from_date : datetime object
    to_date : datetime object
    rand_type : {'uniform'}

    Examples
    --------
    >>> random.seed(28041990)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(1998, 12, 13, 23, 38, 0, 121628)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(2000, 3, 19, 19, 24, 31, 193940)
    """
    delta = to_date - from_date
    if rand_type == 'uniform':
        rand = random.random()
    else:
        raise NotImplementedError('Unknown random mode \'{}\''
                                  .format(rand_type))
    return from_date + rand * delta


def create_df(n=1000):
    """Create a Pandas dataframe with datetime objects."""
    from_date = datetime(1990, 4, 28)
    to_date = datetime(2000, 12, 31)
    sales = [create_random_datetime(from_date, to_date) for _ in range(n)]
    df = pd.DataFrame({'start_date': sales})
    return df


if __name__ == '__main__':
    import doctest
    doctest.testmod()
    df = create_df()
    visualize(df)

5

Tôi đã có thể giải quyết vấn đề này bằng cách (1) vẽ biểu đồ với matplotlib thay vì sử dụng khung dữ liệu trực tiếp và (2) sử dụng valuesthuộc tính. Xem ví dụ:

import matplotlib.pyplot as plt

ax = plt.gca()
ax.hist(column.values)

Điều này không hiệu quả nếu tôi không sử dụng values, nhưng tôi không biết tại sao nó hoạt động.


2

Đây là một giải pháp khi bạn chỉ muốn có một biểu đồ như bạn mong đợi. Điều này không sử dụng groupby, nhưng chuyển đổi các giá trị ngày giờ thành số nguyên và thay đổi nhãn trên biểu đồ. Một số cải tiến có thể được thực hiện để di chuyển các nhãn đánh dấu đến các vị trí đồng đều. Ngoài ra với cách tiếp cận, một biểu đồ ước tính mật độ hạt nhân (và bất kỳ ô nào khác) cũng có thể thực hiện được.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.DataFrame({"datetime": pd.to_datetime(np.random.randint(1582800000000000000, 1583500000000000000, 100, dtype=np.int64))})
fig, ax = plt.subplots()
df["datetime"].astype(np.int64).plot.hist(ax=ax)
labels = ax.get_xticks().tolist()
labels = pd.to_datetime(labels)
ax.set_xticklabels(labels, rotation=90)
plt.show()

Biểu đồ ngày giờ


1

Tôi nghĩ để giải quyết vấn đề đó, bạn có thể sử dụng mã này, nó chuyển đổi kiểu ngày thành kiểu int:

df['date'] = df['date'].astype(int)
df['date'] = pd.to_datetime(df['date'], unit='s')

chỉ để lấy ngày, bạn có thể thêm mã này:

pd.DatetimeIndex(df.date).normalize()
df['date'] = pd.DatetimeIndex(df.date).normalize()

1
điều này không trả lời câu hỏi làm thế nào để vẽ một biểu đồ ngày giờ theo thứ tự?
tàu lượn siêu tốc

Tôi nghĩ vấn đề của bạn tại datetime loại, bạn phải bình thường hóa trước khi bạn lô

Bạn cũng có thể thấy liên kết

1

Tôi cũng gặp rắc rối với điều này. Tôi tưởng tượng rằng vì bạn đang làm việc với ngày tháng nên bạn muốn duy trì thứ tự thời gian (giống như tôi đã làm.)

Cách giải quyết sau đó là

import matplotlib.pyplot as plt    
counts = df['date'].value_counts(sort=False)
plt.bar(counts.index,counts)
plt.show()

Làm ơn, nếu ai biết cách tốt hơn, hãy lên tiếng.

CHỈNH SỬA: đối với jean ở trên, đây là mẫu dữ liệu [Tôi lấy mẫu ngẫu nhiên từ tập dữ liệu đầy đủ, do đó là dữ liệu biểu đồ tầm thường.]

print dates
type(dates),type(dates[0])
dates.hist()
plt.show()

Đầu ra:

0    2001-07-10
1    2002-05-31
2    2003-08-29
3    2006-06-21
4    2002-03-27
5    2003-07-14
6    2004-06-15
7    2002-01-17
Name: Date, dtype: object
<class 'pandas.core.series.Series'> <type 'datetime.date'>

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-f39e334eece0> in <module>()
      2 print dates
      3 print type(dates),type(dates[0])
----> 4 dates.hist()
      5 plt.show()

/anaconda/lib/python2.7/site-packages/pandas/tools/plotting.pyc in hist_series(self, by, ax, grid, xlabelsize, xrot, ylabelsize, yrot, figsize, bins, **kwds)
   2570         values = self.dropna().values
   2571 
-> 2572         ax.hist(values, bins=bins, **kwds)
   2573         ax.grid(grid)
   2574         axes = np.array([ax])

/anaconda/lib/python2.7/site-packages/matplotlib/axes/_axes.pyc in hist(self, x, bins, range, normed, weights, cumulative, bottom, histtype, align, orientation, rwidth, log, color, label, stacked, **kwargs)
   5620             for xi in x:
   5621                 if len(xi) > 0:
-> 5622                     xmin = min(xmin, xi.min())
   5623                     xmax = max(xmax, xi.max())
   5624             bin_range = (xmin, xmax)

TypeError: can't compare datetime.date to float

1

Tất cả những câu trả lời này có vẻ quá phức tạp, ít nhất với gấu trúc 'hiện đại' thì đó là hai dòng.

df.set_index('date', inplace=True)
df.resample('M').size().plot.bar()

1
Điều này dường như chỉ hoạt động nếu bạn có DataFrame, nhưng không hoạt động nếu tất cả những gì bạn có là a Series. Bạn có cân nhắc thêm một ghi chú về trường hợp đó không?
David Z
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.