如何在pandas中按日期绘图并同时进行分组

2 投票
2 回答
6635 浏览
提问于 2025-04-18 05:00

我经常想把一列数据用另一列来绘图,但发现很难通过第三列来分组或区分这些数据。

假设我有这样一个表格:

在这里输入图片描述

我该如何在pandas中创建同样的图表呢?

顺便说一下,我喜欢x轴是线性的,而不是把日期简单地排成一排,因为这样可以更好地显示同一组数据之间的测量是多么接近——但如果距离太远,知道如何处理这两种情况也不错。

更新

来自@Ffisegydd的回答非常有用。不过我接受答案时有点太快了——在实际的Excel表上试代码时我发现了问题。这个问题完全是我的错,因为我没有提供Excel表。@Ffisegydd非常好心地根据我的问题手动创建了数据框,但处理Excel文件有点不同。

对此我深感抱歉。这是一个Excel文件: https://dl.dropboxusercontent.com/u/3216968/Example.xlsx

这是我在IPython笔记本中做到的:

import pandas as pd
import datetime as dt

path2file = r"C:\Example.xlsx"
_xl = pd.ExcelFile(path2file)
df = pd.read_excel(path2file, _xl.sheet_names[0], header=0)
df

在这里输入图片描述

df.Date = df.Date.apply( lambda x: dt.datetime.strptime(x, '%Y.%m.%d').date() )
df

在这里输入图片描述

这里是出错的地方:

pd.DataFrame( data= [df.Data, df.Group], columns = ['Data', 'Group'], index=df.Date)

出现了这个错误

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-9-231baa928f67> in <module>()
----> 1 pd.DataFrame( data= [df.Data, df.Group], columns = ['Data', 'Group'], index=df.Date)

C:\Python27\lib\site-packages\pandas\core\frame.pyc in __init__(self, data, index, columns, dtype, copy)
    245                         index = _default_index(len(data))
    246                     mgr = _arrays_to_mgr(arrays, columns, index, columns,
--> 247                                          dtype=dtype)
    248                 else:
    249                     mgr = self._init_ndarray(data, index, columns, dtype=dtype,

C:\Python27\lib\site-packages\pandas\core\frame.pyc in _arrays_to_mgr(arrays, arr_names, index, columns, dtype)
   4471     axes = [_ensure_index(columns), _ensure_index(index)]
   4472 
-> 4473     return create_block_manager_from_arrays(arrays, arr_names, axes)
   4474 
   4475 

C:\Python27\lib\site-packages\pandas\core\internals.pyc in create_block_manager_from_arrays(arrays, names, axes)
   3757         return mgr
   3758     except (ValueError) as e:
-> 3759         construction_error(len(arrays), arrays[0].shape[1:], axes, e)
   3760 
   3761 

C:\Python27\lib\site-packages\pandas\core\internals.pyc in construction_error(tot_items, block_shape, axes, e)
   3729         raise e
   3730     raise ValueError("Shape of passed values is {0}, indices imply {1}".format(
-> 3731         passed,implied))
   3732 
   3733 def create_block_manager_from_blocks(blocks, axes):

ValueError: Shape of passed values is (2,), indices imply (2, 12)

或者这样做

pd.DataFrame( {'data': df.Data, 'group': df.Group}, index=df.Date)

在这里输入图片描述

2 个回答

2

这个应该可以用

df.pivot_table(rows=['Date'], cols=['Group'], values=['Data']).plot()

不过要注意,每个数据点都是某一天特定组里数据点的“平均值”

3

你可以创建一个叫做 groupby 的对象,然后对这些组进行循环,接着画图。

下面的代码会处理你的数据,并把这两个“组”画出来。还有一些额外的格式设置,让图看起来更好看。

import matplotlib.pyplot as plt
import pandas as pd
import datetime as dt

path2file = r"Example.xlsx"
_xl = pd.ExcelFile(path2file)
df = pd.read_excel(path2file, _xl.sheet_names[0], header=0) 

df.Date = df.Date.apply( lambda x: dt.datetime.strptime(x, '%Y.%m.%d').date())
df.index = df.Date # Set the Date column as your index
del df['Date'] # Remove the Date column from your data columns

grouped = df.groupby('Group') # groupby object

# Normally you would just iterate using "for k, g in grouped:" but the i
# is necessary for selecting a color.
colors = ['red', 'blue']
for i, (k, g) in enumerate(grouped):
    plt.plot_date(g['Data'].index, g['Data'], linestyle='None', marker='o', mfc=colors[i], label=k)

plt.legend()
plt.gcf().autofmt_xdate() # Format the dates with a diagonal slant to make them fit.

# Pad the data out so all markers can be seen.
pad = dt.timedelta(days=7)
plt.xlim((min(df.index)-pad, max(df.index)+pad))
plt.ylim(0,6)

Plot

撰写回答