这是数据:
df = pd.DataFrame({
'date':[1,1,2,2,2,3,3,3,4,5],
'request':[2,2,2,3,3,2,3,3,3,3],
'users':[1,3,7,1,7,3,4,9,7,9],
'count':[1,1,2,3,1,3,1,2,1,1]
})
df
count date request users
0 1 1 2 1
1 1 1 2 3
2 2 2 2 7
3 3 2 3 1
4 1 2 3 7
5 3 3 2 3
6 1 3 3 4
7 2 3 3 9
8 1 4 3 7
9 1 5 3 9
我们的想法是按count
和date
分组,并将每隔一列转换为分组值列表。我认为这就像调用dfgp.agg
一样简单但事实并非如此。
这就是我想要做的事情:
date request count users
0 1 2 [1, 1] [1, 3]
1 2 2 [2] [7]
2 2 3 [3, 1] [1, 7]
3 3 2 [3] [3]
4 3 3 [1, 2] [4, 9]
5 4 3 [1] [7]
6 5 3 [1] [9]
我就是这样做的:
grouped_df = df.groupby(['date', 'request'])
df_new = pd.DataFrame({ 'count' : grouped_df['count'].apply(list), 'users' : grouped_df['users'].apply(list) }).reset_index()
它有效但我相信必须有更好的方法......可以在分组对象中的所有列上工作。例如,我应该只按date
分组,解决方案应该有效。我的解决方案将依赖于对我不喜欢的列进行硬编码,因此在这种情况下它会失败。
这是困扰我的事情。它应该是一个明显的解决方案,但我找不到它。还有更好的方法吗?
调用我所有的Pandas MVP ......
答案 0 :(得分:1)
df.groupby(['request','date'])[['count','users']].agg(lambda x: ','.join(x.astype(str)))
输出:
count users
request date
2 1 1,1 1,3
2 2 7
3 3 3
3 2 3,1 1,7
3 1,2 4,9
4 1 7
5 1 9
答案 1 :(得分:1)
更好的答案
查找重复发生的位置,拆分并相应地过滤
dups = df.duplicated(['request', 'date'], 'last').values
i = np.where(~dups[:-1])[0] + 1
r, d, c, u = (df[c].values for c in df)
d1 = pd.DataFrame(
np.column_stack([r[~dups], d[~dups]]), columns=['request', 'date'])
d2 = pd.DataFrame(
np.column_stack([np.split(c, i), np.split(u, i)]), columns=['count', 'users'])
d1.join(d2)
date requeset count users
0 1 2 [1, 1] [1, 3]
1 2 2 [2] [7]
2 2 3 [3, 1] [1, 7]
3 3 2 [3] [3]
4 3 3 [1, 2] [4, 9]
5 4 3 [1] [7]
6 5 3 [1] [9]
回答我感觉很好!
好极了! defaultdict
from collections import defaultdict
d = defaultdict(list)
s = df.set_index(['date', 'request']).stack()
[d[k].append(v) for k, v in s.iteritems()];
pd.Series(d).unstack().rename_axis(['date', 'requeset']).reset_index()
date requeset count users
0 1 2 [1, 1] [1, 3]
1 2 2 [2] [7]
2 2 3 [3, 1] [1, 7]
3 3 2 [3] [3]
4 3 3 [1, 2] [4, 9]
5 4 3 [1] [7]
6 5 3 [1] [9]
旧答案
f = lambda x: pd.Series(x.values.T.tolist(), x.columns)
df.groupby(['request', 'date'])[['count', 'users']].apply(f).reset_index()
request date count users
0 2 1 [1, 1] [1, 3]
1 2 2 [2] [7]
2 2 3 [3] [3]
3 3 2 [3, 1] [1, 7]
4 3 3 [1, 2] [4, 9]
5 3 4 [1] [7]
6 3 5 [1] [9]
挫折答案!
Shoehorning agg
from ast import liter_eval
df.groupby(['request', 'date']).agg(
lambda x: str(list(x))
).applymap(literal_eval).reset_index()
request date count users
0 2 1 [1, 1] [1, 3]
1 2 2 [2] [7]
2 2 3 [3] [3]
3 3 2 [3, 1] [1, 7]
4 3 3 [1, 2] [4, 9]
5 3 4 [1] [7]
6 3 5 [1] [9]
答案 2 :(得分:1)
使用apply
的Hacky方式,可能会非常慢。
In [1274]: df.groupby(['date', 'request']).apply(
lambda x: pd.Series({c: x[c].tolist() for c in ['count', 'users']}))
Out[1274]:
count users
date request
1 2 [1, 1] [1, 3]
2 2 [2] [7]
3 [3, 1] [1, 7]
3 2 [3] [3]
3 [1, 2] [4, 9]
4 3 [1] [7]
5 3 [1] [9]