我有以下示例数据:
U_ID Group Location Hours Date
79 149 17 USA 2 2014-11-03
80 149 17 USA 2 2014-11-07
81 149 21 USA 3 2014-12-21
82 149 18 UK 1.5 2014-11-14
83 149 19 Spain 2 2014-11-21
我希望对组和位置相同的同月的小时数进行求和:
79 149 17 USA 2 2014-11-03
80 149 17 USA 2 2014-11-07
将在新数据框中变为以下内容:
1 149 17 USA 4 2014-11-01
除了可以最有效地选择与给定年份和月份匹配的数据的方式之外,我可以解决其中的大部分问题,因此在此示例中,我将如何选择2014年11月的所有内容?
我打算逐行遍历帧,然后跟踪已处理的行(因此我不会创建重复项):
def process_ids(s_df): 已处理ID = pd.DataFrame(columns = ['U_ID'],dtype ='str')
for i, row in s_df.iterrows():
if processed_ids['U_ID'].str.contains(row['U_ID']).any():
continue
else:
processed_ids = processed_ids.append({"U_ID": str(row['U_ID'])}, ignore_index=True)
我现在只需要按年份和月份进行过滤,然后检查它们是否具有相同的组和位置
答案 0 :(得分:1)
将groupby
与Grouper
汇总在一起使用,以按月MS
开始分组:
df1 = (df.groupby(['U_ID', 'Group', 'Location',pd.Grouper(key='Date', freq='MS')])['Hours']
.sum()
.reset_index())
print (df1)
U_ID Group Location Date Hours
0 149 17 USA 2014-11-01 4.0
1 149 18 UK 2014-11-01 1.5
2 149 19 Spain 2014-11-01 2.0
3 149 21 USA 2014-12-01 3.0
然后通过boolean indexing
选择:
print (df1[df1['Date'] == '2014-11-01'])
U_ID Group Location Date Hours
0 149 17 USA 2014-11-01 4.0
1 149 18 UK 2014-11-01 1.5
2 149 19 Spain 2014-11-01 2.0
print (df1[df1['Date'] == '2014-12-01'])
U_ID Group Location Date Hours
3 149 21 USA 2014-12-01 3.0
如果可能要按datetime
进行选择,可以对DatetimeIndex
进行一些更改:
df1 = (df.groupby(['U_ID', 'Group', 'Location',pd.Grouper(key='Date', freq='MS')])['Hours']
.sum()
.reset_index(level=[0,1,2]))
print (df1)
U_ID Group Location Hours
Date
2014-11-01 149 17 USA 4.0
2014-11-01 149 18 UK 1.5
2014-11-01 149 19 Spain 2.0
2014-12-01 149 21 USA 3.0
然后按partial string indexing
进行选择:
print (df1['2014-11'])
U_ID Group Location Hours
Date
2014-11-01 149 17 USA 4.0
2014-11-01 149 18 UK 1.5
2014-11-01 149 19 Spain 2.0
print (df1['2014-12'])
U_ID Group Location Hours
Date
2014-12-01 149 21 USA 3.0
编辑:
如果还希望为非聚合组保留原始Date
,则一种可能的解决方案是为size
添加计数组聚合字典并聚合first
,最后用{ {3}}仅一个行组,长度为1:
df1 = (df.groupby(['U_ID', 'Group', 'Location', pd.Grouper(key='Date', freq='MS')])
.agg({'Hours':'sum', 'U_ID':'size','Date':'first'})
.rename(columns={'Date':'processed date','U_ID':'len group'})
.reset_index()
)
df1['processed date'] = np.where(df1['len group'].eq(1), df1['processed date'], df1['Date'])
print (df1)
U_ID Group Location Date Hours len group processed date
0 149 17 USA 2014-11-01 4.0 2 2014-11-01
1 149 18 UK 2014-11-01 1.5 1 2014-11-14
2 149 19 Spain 2014-11-01 2.0 1 2014-11-21
3 149 21 USA 2014-12-01 3.0 1 2014-12-21