【问题标题】:Groupby certain months and sum values in pandas dataframe对熊猫数据框中的某些月份和总和值进行分组
【发布时间】:2018-04-25 14:53:34
【问题描述】:

我有一个数据框df,看起来像这样,没有设置索引:

df.head()

    year    month   inch    mm
0   1981    2       0.00    0.000
1   1981    3       4.82    122.428
2   1981    4       6.45    163.830
3   1981    5       5.03    127.762
4   1981    6       1.25    31.750

(1) 首先,我只想选择 1987 年到 2017 年之间的年份。

(2) 然后我想按年份分组选择月份:MAM(所以 3-5)、JJAS(6-9)和 OND(10-12),并对这些月份的 mm 列求和。

结果可能如下所示:

year   season   mm
1981   MAM      360
1981   JJAS     167
...

我不确定如何执行第 1 部分,但我知道对于第 2 部分,我需要将 month 列转换为日期时间对象。

然后我会通过以下方式定义兴趣月份:

MAM = df.iloc[df.index.month.isin(np.r_[3:6])]
JJAS = df.iloc[df.index.month.isin(np.r_[6:10])]
OND = df.iloc[df.index.month.isin(np.r_[10:13])]

但现在我收到错误AttributeError: 'RangeIndex' object has no attribute 'month'

提前致谢!

【问题讨论】:

    标签: python pandas dataframe group-by


    【解决方案1】:

    第一部分非常简单。使用pd.Series.between:

    df = df[df.year.between(1987, 2017)]
    

    如果year 未排序,我建议先排序df,然后使用sort_values(subset='year') 进行排序。

    对于下一部分,一种解决方案是生成一个dict 映射,然后使用mapmonth 转换为您的映射字符串,然后对其进行分组。

    mapping = {3 : 'MAM', 4 : 'MAM', 5 : 'MAM', 6 : 'JJAS' ,... } # complete this
    r = df.groupby(['year', df.month.map(mapping)]).sum()
    

    【讨论】:

    • 嗨@cᴏʟᴅsᴘᴇᴇᴅ。这几乎奏效了。唯一的事情是它总结了所有年份的 JJAS、MAM、OND 值。所以现在它看起来像这样:month year month mm JJAS 240180 900 4906.636301 MAM 186186 372 6569.026143 OND 180135 990 4047.652123 我想将每个季节每年的总和。
    • @JAG2024 好的,只需添加一个额外的 group 子句,它应该可以工作(见编辑)。
    • @JAG2024 保持优雅。
    【解决方案2】:

    这里有一个稍微不同的方法:使用 yearmonth 构建索引,然后使用 groupby() 和 UDF。

    示例数据:

    N = 10
    years = pd.date_range("1981", "2017", freq="A").year
    dates = np.random.choice(years, size=N, replace=True)
    months = np.random.choice(range(1,13), size=N, replace=True)
    inches = np.random.randint(1,20, size=N)
    mm = np.random.randint(1,100, size=N)
    data = {"year":dates, "month":months, "inch":inches, "mm":mm}
    df = pd.DataFrame(data)
    
    df
       inch  mm  month  year
    0    19  31     12  1990
    1     8  71      9  1986
    2     5  85      2  2009
    3    17   8     12  2005
    4    10  14     12  1987
    5     7  87      2  1982
    6     8  59      2  2004
    7     8  74      8  2016
    8     5   6      6  1993
    9     3   7     12  1982
    

    现在根据年份子集并建立索引:

    mask = df.year.between(1987, 2017)
    df.index = df.apply(lambda x: pd.to_datetime("{0} {1}".format(x.year, x.month), 
                                                 format="%Y %m"), axis=1)
    

    然后使用year 和月份分隔功能进行分组:

    def month_gb(x):
        if x.month in range(3,6):
            return 'MAM'
        elif x.month in range(6,10):
            return 'JJAS'
        elif x.month in range(10,13):
            return 'OND'
    
    df.loc[mask].groupby(["year", month_gb]).mm.sum()
    
    year      
    1987  OND     14
    1990  OND     31
    1993  JJAS     6
    2005  OND      8
    2016  JJAS    74
    Name: mm, dtype: int64
    

    【讨论】:

    • 这也很棒。谢谢@andrew_reece
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    相关资源
    最近更新 更多