【问题标题】:plot year over year on 12 month axis在 12 个月轴上逐年绘制
【发布时间】:2014-03-14 23:07:16
【问题描述】:

我想从 12 月到 1 月在一个 12 个月的轴上绘制 6 年的 12 个月期间数据。

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

df = pd.Series(np.random.randn(72), index=pd.date_range('1/1/2000', periods=72, freq='M'))

# display(df.head())
2000-01-31    0.713724
2000-02-29    0.416233
2000-03-31   -0.147765
2000-04-30    0.141021
2000-05-31    0.966261
Freq: M, dtype: float64

grouped = df.groupby(df.index.map(lambda x: x.year))

grouped.plot()

我在每年之间的界限中得到了突破。但是,我想做的是让年份彼此叠加。有什么简单干净的方法吗?

【问题讨论】:

    标签: python matplotlib pandas


    【解决方案1】:

    可能还有比这更好的方法:

    In [44]: vals = df.groupby(lambda x: (x.year, x.month)).sum()
    
    In [45]: vals
    Out[45]: 
    (2000, 1)    -0.235044
    (2000, 2)    -1.196815
    (2000, 3)    -0.370850
    (2000, 4)     0.719915
    (2000, 5)    -1.228286
    (2000, 6)    -0.192108
    (2000, 7)    -0.337032
    (2000, 8)    -0.174219
    (2000, 9)     0.605742
    (2000, 10)    1.061558
    (2000, 11)   -0.683674
    (2000, 12)   -0.813779
    (2001, 1)     2.103178
    (2001, 2)    -1.099845
    (2001, 3)     0.366811
    ...
    (2004, 10)   -0.905740
    (2004, 11)   -0.143628
    (2004, 12)    2.166758
    (2005, 1)     0.944993
    (2005, 2)    -0.741785
    (2005, 3)     1.531754
    (2005, 4)    -1.106024
    (2005, 5)    -1.925078
    (2005, 6)     0.400930
    (2005, 7)     0.321962
    (2005, 8)    -0.851656
    (2005, 9)     0.371305
    (2005, 10)   -0.868836
    (2005, 11)   -0.932977
    (2005, 12)   -0.530207
    Length: 72, dtype: float64
    

    现在将vals 上的索引更改为MultiIndex

    In [46]: vals.index = pd.MultiIndex.from_tuples(vals.index)
    
    In [47]: vals.head()
    Out[47]: 
    2000  1   -0.235044
          2   -1.196815
          3   -0.370850
          4    0.719915
          5   -1.228286
    dtype: float64
    

    然后解栈并绘图:

    In [48]: vals.unstack(0).plot()
    Out[48]: <matplotlib.axes.AxesSubplot at 0x1171a2dd0>
    

    【讨论】:

      【解决方案2】:
      1. 如果数据是pandas.DataFrame,而不是pandas.Series,我认为它更清晰,更容易转换。
        • OP 中的示例数据是pandas.Series,但对于希望解决这个问题的人来说,它会更典型,如果我们以pandas.DataFrame 开头,那么我们将从使用.to_frame() 开始
      2. 提取datetime 索引的monthyear 组件。
        • 这个索引已经是datetime dtype;如果您的数据不是,请使用pd.to_datetime() 转换日期索引/列
        • 如果数据是列而不是索引,则使用.dt 访问器获取monthyear(例如df[col].dt.yeardf.index.year
      3. 使用pandas.pivot_table将数据帧从长格式转换为宽格式,并聚合数据(例如'sum''mean'等)
        • 这会将数据框设置为正确的形状,以便轻松绘制,无需拆垛和进一步操作。
        • 索引将始终为 x 轴,并且将绘制列。
        • 如果给定'month' 没有重复数据,因此不需要聚合,则使用pandas.DataFrame.pivot
      4. 使用pandas.DataFrame.plot 绘制旋转数据框
      • python 3.8.11pandas 1.3.2matplotlib 3.4.3中测试
      import pandas as pd
      
      # for this OP convert the Series to a DataFrame
      df = df.to_frame()
      
      # extract month and year from the index and create columns
      df['month'] = df.index.month
      df['year'] = df.index.year
      
      # display(df.head(3))
                         0  month  year
      2000-01-31  0.167921      1  2000
      2000-02-29  0.523505      2  2000
      2000-03-31  0.817376      3  2000
      
      # transform the dataframe to a wide format
      dfp = pd.pivot_table(data=df, index='month', columns='year', values=0, aggfunc='sum')
      
      # display(dfp.head(3))
      year       2000      2001      2002      2003      2004      2005
      month                                                            
      1      0.167921  0.637999 -0.174122  0.620622 -0.854315 -1.523579
      2      0.523505 -0.344658 -0.280819  0.845543  0.782439 -0.593732
      3      0.817376 -0.004282 -0.907424  0.352655  1.258275 -0.624112
      
      # plot
      ax = dfp.plot(ylabel='Aggregated Sum', figsize=(6, 4))
      ax.set_xticks(dfp.index)  # so every month number is displayed
      ax.legend(bbox_to_anchor=(1, 1.02), loc='upper left')
      

      • 要获取轴上的月份名称,请使用以下命令创建 'month' 列:
        • df['month'] = df.index.strftime('%b'),获取月份缩写
      from calendar import month_abbr  # this is a sorted list of month name abbreviations
      
      # extract the month abbreviation
      df['month'] = df.index.strftime('%b')
      df['year'] = df.index.year
      
      # transform
      dfp = pd.pivot_table(data=df, index='month', columns='year', values=0, aggfunc='sum')
      
      # the dfp index so the x-axis will be in order
      dfp = dfp.loc[month_abbr[1:]]
      
      # display(dfp.head(3))
      year       2000      2001      2002      2003      2004      2005
      month                                                            
      Jan    0.167921  0.637999 -0.174122  0.620622 -0.854315 -1.523579
      Feb    0.523505 -0.344658 -0.280819  0.845543  0.782439 -0.593732
      Mar    0.817376 -0.004282 -0.907424  0.352655  1.258275 -0.624112
      
      # plot
      ax = dfp.plot(ylabel='Aggregated Sum', figsize=(6, 4))
      ax.set_xticks(range(12))  # set ticks for all months
      ax.set_xticklabels(dfp.index)  # label all the ticks
      ax.legend(bbox_to_anchor=(1, 1.02), loc='upper left')
      

      • 此数据是离散数据,因为它是聚合的,因此确实应该绘制为条形图。
      ax = dfp.plot(kind='bar', ylabel='Aggregated Sum', figsize=(12, 4), rot=0)
      ax.legend(bbox_to_anchor=(1, 1.02), loc='upper left')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-07
        • 1970-01-01
        • 2021-07-24
        • 2021-08-31
        • 2021-12-29
        • 2019-02-19
        • 2018-12-08
        • 2013-07-07
        相关资源
        最近更新 更多