通过在具有 pandas 的列上分组来汇总数据框
Summarize dataframe by grouping on a column with pandas
我有一个数据框
id store val1 val2
1 abc 20 30
1 abc 20 40
1 qwe 78 45
2 dfd 34 45
2 sad 43 45
由此我必须在 id
上分组并创建一个新的 df,其中包含 total_store
和 unique stores
以及 non-repeating_stores
列,其中包含此类计数存储事件。
我的最终输出应该是
id total_store unique stores non-repeating_stores
1 3 2 1
2 2 2 2
我可以通过
获得总商店
df.groupby('id')['store'].count()
但是我如何获取其他数据并从中形成数据框
您可以使用 groupby
+ agg
。
df = df.groupby('id').store.agg(['count', 'nunique', \
lambda x: x.drop_duplicates(keep=False).size])
df.columns = ['total_store', 'unique stores', 'non-repeating_stores']
df
total_store unique stores non-repeating_stores
id
1 3 2 1
2 2 2 2
对于较旧的 pandas 版本,传递字典可以简化您的代码(在 0.20
及以后的版本中已弃用):
agg_funcs = {'total_stores' : 'count', 'unique_stores' : 'nunique',
'non-repeating_stores' : lambda x: x.drop_duplicates(keep=False).size
}
df = df.groupby('id').store.agg(agg_funcs)
df
total_stores non-repeating_stores unique_stores
id
1 3 1 2
2 2 2 2
作为速度的轻微改进,您可以使用 drop_duplicates
的姊妹方法,duplicated
,以这种方式,:
lambda x: (~x.duplicated(keep=False)).sum()
这将取代 agg
中的第三个函数,对大小 1000000
:
的大数据有 20% 的速度提升
1 loop, best of 3: 7.31 s per loop
v/s
1 loop, best of 3: 5.19 s per loop
将groupby
with agg
with count
and nunique
. Last function is a bit complicated - need count all non dupes using inverting duplicated
与sum
一起使用:
如果需要计数 NaN
s 使用 size
代替 count
:
df = df.groupby('id')['store'].agg(['count',
'nunique',
lambda x: (~x.duplicated(keep=False)).sum()])
df.columns = ['total_store', 'unique stores', 'non-repeating_stores']
print (df)
total_store unique stores non-repeating_stores
id
1 3 2 1
2 2 2 2
时间:
np.random.seed(123)
N = 1000000
L = np.random.randint(10000,size=N).astype(str)
df = pd.DataFrame({'store': np.random.choice(L, N),
'id': np.random.randint(10000, size=N)})
print (df)
In [120]: %timeit (df.groupby('id')['store'].agg(['count', 'nunique', lambda x: (~x.duplicated(keep=False)).sum()]))
1 loop, best of 3: 4.47 s per loop
In [122]: %timeit (df.groupby('id').store.agg(['count', 'nunique', lambda x: x.drop_duplicates(keep=False).size]))
1 loop, best of 3: 11 s per loop
我有一个数据框
id store val1 val2
1 abc 20 30
1 abc 20 40
1 qwe 78 45
2 dfd 34 45
2 sad 43 45
由此我必须在 id
上分组并创建一个新的 df,其中包含 total_store
和 unique stores
以及 non-repeating_stores
列,其中包含此类计数存储事件。
我的最终输出应该是
id total_store unique stores non-repeating_stores
1 3 2 1
2 2 2 2
我可以通过
获得总商店df.groupby('id')['store'].count()
但是我如何获取其他数据并从中形成数据框
您可以使用 groupby
+ agg
。
df = df.groupby('id').store.agg(['count', 'nunique', \
lambda x: x.drop_duplicates(keep=False).size])
df.columns = ['total_store', 'unique stores', 'non-repeating_stores']
df
total_store unique stores non-repeating_stores
id
1 3 2 1
2 2 2 2
对于较旧的 pandas 版本,传递字典可以简化您的代码(在 0.20
及以后的版本中已弃用):
agg_funcs = {'total_stores' : 'count', 'unique_stores' : 'nunique',
'non-repeating_stores' : lambda x: x.drop_duplicates(keep=False).size
}
df = df.groupby('id').store.agg(agg_funcs)
df
total_stores non-repeating_stores unique_stores
id
1 3 1 2
2 2 2 2
作为速度的轻微改进,您可以使用 drop_duplicates
的姊妹方法,duplicated
,以这种方式,
lambda x: (~x.duplicated(keep=False)).sum()
这将取代 agg
中的第三个函数,对大小 1000000
:
1 loop, best of 3: 7.31 s per loop
v/s
1 loop, best of 3: 5.19 s per loop
将groupby
with agg
with count
and nunique
. Last function is a bit complicated - need count all non dupes using inverting duplicated
与sum
一起使用:
如果需要计数 NaN
s 使用 size
代替 count
:
df = df.groupby('id')['store'].agg(['count',
'nunique',
lambda x: (~x.duplicated(keep=False)).sum()])
df.columns = ['total_store', 'unique stores', 'non-repeating_stores']
print (df)
total_store unique stores non-repeating_stores
id
1 3 2 1
2 2 2 2
时间:
np.random.seed(123)
N = 1000000
L = np.random.randint(10000,size=N).astype(str)
df = pd.DataFrame({'store': np.random.choice(L, N),
'id': np.random.randint(10000, size=N)})
print (df)
In [120]: %timeit (df.groupby('id')['store'].agg(['count', 'nunique', lambda x: (~x.duplicated(keep=False)).sum()]))
1 loop, best of 3: 4.47 s per loop
In [122]: %timeit (df.groupby('id').store.agg(['count', 'nunique', lambda x: x.drop_duplicates(keep=False).size]))
1 loop, best of 3: 11 s per loop