Python Groupby数据框中的特定月份和总和值

Python Groupby数据框中的特定月份和总和值,python,pandas,dataframe,group-by,Python,Pandas,Dataframe,Group By,我有一个数据帧df,看起来像这样,没有设置索引: df.head() (1) 首先,我只想选择1987年和2017年之间的年份 (2) 然后我想对所选月份按年份分组:MAM(so 3-5)、JJAS(6-9)和OND(10-12),并对这些月份的mm列求和 结果可能如下所示: year season mm 1981 MAM 360 1981 JJAS 167 ... 我不确定如何执行第1部分,但我知道对于第2部分,我需要将month列转换为日期时间对象 然后,

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

df.head()

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

(2) 然后我想对所选月份按年份分组:MAM(so 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'对象没有属性'month'


提前谢谢

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

df = df[df.year.between(1987, 2017)]
如果未对
year
进行排序,我建议先对
df
进行排序,然后使用
sort\u值(subset='year')
进行排序

在下一部分中,一个解决方案将涉及生成
dict
映射,然后使用
map
month
转换为映射字符串,并在该字符串上分组

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

第一部分相当简单。使用
pd.Series.between

df = df[df.year.between(1987, 2017)]
如果未对
year
进行排序,我建议先对
df
进行排序,然后使用
sort\u值(subset='year')
进行排序

在下一部分中,一个解决方案将涉及生成
dict
映射,然后使用
map
month
转换为映射字符串,并在该字符串上分组

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

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

示例数据:

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)
然后,使用
和月分隔功能进行分组:

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

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

示例数据:

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)
然后,使用
和月分隔功能进行分组:

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

嗨@cᴏʟᴅsᴘᴇᴇᴅ. 这几乎奏效了。唯一的一点是它总结了所有年份的JJA、MAM、OND值。现在看起来是这样的:
month-year-month-mm JJAS 240180 900 4906.636301 MAM 186186 372 6569.026143 OND 180135 990 4047.652123
我希望每年对每个季节进行汇总。@JAG2024好的,只需添加一个额外的组子句,它应该会起作用(请参见编辑)。@JAG2024保持优雅。Hi@cᴏʟᴅsᴘᴇᴇᴅ. 这几乎奏效了。唯一的一点是它总结了所有年份的JJA、MAM、OND值。现在看起来是这样的:
month-year-month-mm-JJAS 240180 900 4906.636301-MAM 186186186372 6569.026143-OND 180135 990 4047.652123
我希望每年都有一个季度的总结。@JAG2024好吧,只需添加一个额外的分组条款,它应该会起作用(请参见编辑)。@JAG2024保持优雅。这也非常棒。谢谢@andrew_Reeceth这也太棒了。谢谢@andrew_reece