我想按日期分组后产生一个摘要数据框。我想要一个列,它按原样显示给定列的平均值,并过滤掉大于0的实例后,显示同一列的平均值。我想出了如何做到这一点(如下),但是它需要这样做两个单独的groupby
调用,重命名这些列,然后将它们重新结合在一起。我跌倒了,一个人应该能够一次完成所有操作。我试图使用eval
来执行此操作,但一直出现错误,并被告知要使用apply
,无法在groupby对象上使用eval
。
代码可以让我得到我想要的东西,但效率似乎不高:
# Sample data
data = pd.DataFrame(
{"year" : [2013, 2013, 2013, 2014, 2014, 2014],
"month" : [1, 2, 3, 1, 2, 3],
"day": [1, 1, 1, 1, 1, 1],
"delay": [0, -4, 50, -60, 9, 10]})
subset = (data
.groupby(['year', 'month', 'day'])['delay']
.mean()
.reset_index()
.rename(columns = {'delay' : 'avg_delay'})
)
subset_1 = (data[data.delay > 0]
.groupby(['year', 'month', 'day'])['delay']
.mean()
.reset_index()
.rename(columns = {'delay' : 'avg_delay_pos'})
)
combined = pd.merge(subset, subset_1, how='left', on=['year', 'month', 'day'])
combined
year month day avg_delay avg_delay_pos
0 2013 1 1 0 NaN
1 2013 2 1 -4 NaN
2 2013 3 1 50 50.0
3 2014 1 1 -60 NaN
4 2014 2 1 9 9.0
5 2014 3 1 10 10.0
答案 0 :(得分:1)
IIUC,您可以使用以下代码:
delay
说明:
我首先删除avg_delay
列,并将其分配给新名称delay
,所以我实际上将avg_delay
的名称重命名为avg_delay_pos
然后,我创建一个名为loc
的新列,该列首先使用avg_delay
来获取大于零的值,并且由于索引不会重置,因此它将创建索引值大于NaN
的值大于零,而其他值将不包含任何赋值,即它们将是您期望的{{1}}。
答案 1 :(得分:0)
该解决方案特定于您的问题,但是您可以使用单个groupby调用来实现。要获取“ avg_delay_pos”,您只需删除负(和零)值即可。
df['delay_pos'] = df['delay'].where(df['delay'] > 0)
(df.filter(like='delay')
.groupby(pd.to_datetime(df[['year', 'month', 'day']]))
.mean()
.add_prefix('avg_'))
avg_delay avg_delay_pos
2013-01-01 0 NaN
2013-02-01 -4 NaN
2013-03-01 50 50.0
2014-01-01 -60 NaN
2014-02-01 9 9.0
2014-03-01 10 10.0
故障
where
用于屏蔽非正值。
df['delay_pos'] = df['delay'].where(df['delay'] > 0)
# df['delay'].where(df['delay'] > 0)
0 NaN
1 NaN
2 50.0
3 NaN
4 9.0
5 10.0
Name: delay, dtype: float64
接下来,提取我们要分组的延迟列,
df.filter(like='delay')
delay delay_pos
0 0 NaN
1 -4 NaN
2 50 50.0
3 -60 NaN
4 9 9.0
5 10 10.0
然后在该日期执行groupby
_.groupby(pd.to_datetime(df[['year', 'month', 'day']])).mean()
delay delay_pos
2013-01-01 0 NaN
2013-02-01 -4 NaN
2013-03-01 50 50.0
2014-01-01 -60 NaN
2014-02-01 9 9.0
2014-03-01 10 10.0
在使用pd.to_datetime
将年/月/日列转换为单个datetime列的情况下,对单个列进行分组比对多个列进行分组更为有效。
pd.to_datetime(df[['year', 'month', 'day']])
0 2013-01-01
1 2013-02-01
2 2013-03-01
3 2014-01-01
4 2014-02-01
5 2014-03-01
dtype: datetime64[ns]
最后的.add_prefix('avg_')
向结果添加前缀“ _avg”。
如果您想要单独的年/月/日列,则可以采用另一种方法
df['delay_pos'] = df['delay'].where(df['delay'] > 0)
df.groupby(['year', 'month', 'day']).mean().add_prefix('avg_').reset_index()
year month day avg_delay avg_delay_pos
0 2013 1 1 0 NaN
1 2013 2 1 -4 NaN
2 2013 3 1 50 50.0
3 2014 1 1 -60 NaN
4 2014 2 1 9 9.0
5 2014 3 1 10 10.0