python - 每年用 Pandas 绘制箱线图

标签 python pandas grouping boxplot

我有一个 DataFrame(多个每日时间序列),其中 DateTimeIndex 作为索引MultiIndex 作为。我想选择一列并创建一个箱线图,其中数据按年份分组。我认为这很容易,但我正在努力获得一些结果。

>>> daily.shape
(11319, 118)

>>> daily.index
DatetimeIndex(['1986-01-01', '1986-01-02', '1986-01-03', '1986-01-04',
               '1986-01-05', '1986-01-06', '1986-01-07', '1986-01-08',
               '1986-01-09', '1986-01-10',
               ...
               '2016-12-22', '2016-12-23', '2016-12-24', '2016-12-25',
               '2016-12-26', '2016-12-27', '2016-12-28', '2016-12-29',
               '2016-12-30', '2016-12-31'],
              dtype='datetime64[ns]', name='timevalue', length=11319, freq=None)
>>> daily.columns
MultiIndex(levels=[['41B001', '41B004', '41B006', '41B008', '41B011', '41MEU1', '41N043', '41R001', '41R002', '41R012', '41WOL1', '41WOL2', '47E013', 'T1M001', 'T1M003'], ['BA-10.0', 'BA-2.5', 'BC', 'CO', 'CO2', 'NO', 'NO2', 'NOx', 'O3', 'PM-10.0', 'PM-2.5', 'RH', 'SO2', 'T', 'UVPM', 'VO-10.0', 'VO-2.5', 'WD', 'WS-s', 'WS-v', 'p']],
           labels=[[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14], [5, 6, 7, 3, 5, 6, 7, 8, 3, 5, 6, 7, 8, 3, 5, 6, 7, 12, 0, 1, 5, 6, 7, 8, 9, 10, 15, 16, 0, 1, 5, 6, 7, 9, 10, 15, 16, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 2, 3, 4, 5, 6, 7, 12, 14, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 0, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15, 4, 5, 6, 7, 12, 11, 13, 13, 17, 18, 19, 20, 11, 13, 13, 17, 18, 19, 20]],
           names=['sitekey', 'measurandkey'])

我能达到的最好成绩是:

fig, axe = plt.subplots()
daily.loc[:,[('41R001', 'SO2')]].groupby(daily.index.map(lambda x: x.year)).boxplot(ax=axe, subplots=False, rot=90)

但是它需要其他后处理来标记轴。

当我尝试 reset_index() 应用函数并使用 pivot() 时,由于 MultiIndex,出现索引错误。

d = daily.reset_index()
d['timevalue']

异常(exception)是:无法处理非唯一的多重索引!我不明白,因为我的 MultiIndex 中没有出现 TimeValue。我也尝试过 .loc[] 但我认为问题出在其他地方。

所以,我要实现的目标很简单:

  • 我有多年来的每日时间序列,并且这些时间序列是多索引的;
  • 我想选择其中一个(使用 loc 和复合键,如上例所示)并获得一个时间序列箱线图,其中数据按年份分组。

我认为这可能很简单,但由于多索引错误,我无法正确使用 pivot() 与此 DataFrame。

最佳答案

如果您不介意使用seaborn库,您可以非常轻松地绘制此图:

import pandas as pd
import seaborn as sns

index = pd.DatetimeIndex(start=pd.to_datetime('1985-01-01'), 
                         end = pd.to_datetime('2017-03-08'), 
                         freq='d')
df = pd.DataFrame(index = index, 
                  data = np.random.uniform(-1,1,size=(index.shape[0],4)), 
                  columns=pd.MultiIndex.from_arrays([['A','A','B','B'],
                                                     ['d','e','d','e']]))
df['Year'] = df.index.year
#                    A                   B            Year
#                    d         e         d         e      
# 1985-01-01  0.205208 -0.228484  0.296273  0.545031  1985
# 1985-01-02  0.546436 -0.538920  0.173388  0.848590  1985
# 1985-01-03 -0.367593 -0.974911 -0.796331 -0.946239  1985
# 1985-01-04 -0.346102 -0.951542 -0.975172  0.951099  1985
# 1985-01-05  0.973975  0.708254 -0.150454  0.145298  1985

ax = sns.boxplot(data = df, x='Year',y=('A','e'))
for item in ax.get_xticklabels():
    item.set_rotation(90)

生成的图像:

yearly boxplot

我尝试使用 pandas.DataFrame.boxplot() 方法,但无法在短时间内使其适用于这种情况 =)。

关于python - 每年用 Pandas 绘制箱线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43065157/

相关文章:

python - 数据帧中的多 numpy 数组

python - Pandas date_range 从 DatetimeIndex 到 Date 格式

python - pandas 更改重复行的特定列值

javascript - 从对象数组创建多级组

windows - 如何按共享列值对 CSV 行进行分组和求和?

python - 在单个 python 正则表达式中使用匹配的数字作为重复计数

python - 如何在 UML 中建模递归调用

python - 以编程方式调用 VS 开发人员命令提示符中的命令

.net - SSRS 2008 - 组内排序

python - 矢量化代码与 numpy 中标准循环的不同结果