根据Python Pandas中的其他列对列进行分组

sha*_*dzy 3 python pandas

假设我有以下内容pd.DataFrame:

Name | Color
------------------------------
John | Blue
Greg | Red
John | Yellow
Greg | Red
Greg | Blue
Run Code Online (Sandbox Code Playgroud)

我想得到一个表格,列出每个名字的不同颜色 - 多少和它们的价值.意思是这样的:

Name | Distinct | Values
--------------------------------------
John |   2      | Blue, Yellow
Greg |   2      | Red, Blue
Run Code Online (Sandbox Code Playgroud)

有什么想法怎么做?

cs9*_*s95 5

使用groupby+ agg,传递list聚合函数的自定义:

f = [
        ('Distinct', 'nunique'), 
        ('Values', lambda x: ', '.join(x.unique()))
]

df.groupby('Name').Color.agg(f).reset_index()

   Name  Distinct        Values
0  Greg         2     Red, Blue
1  John         2  Blue, Yellow
Run Code Online (Sandbox Code Playgroud)

计时

一,设置 -

df = pd.DataFrame(
      np.random.randint(0, 1000, (10000, 2)).astype(str), columns=['Name', 'Color']
)
Run Code Online (Sandbox Code Playgroud)

接下来,时间安排.看起来似乎pd.Series.unique太慢了(慢了4倍).为了性能,我将使用np.unique:

# in this answer

%%timeit
f = [
        ('Distinct', 'nunique'), 
        ('Values', lambda x: ', '.join(np.unique(x.values).tolist()))
]

df.groupby('Name').Color.agg(f).reset_index()

122 ms ± 1.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

使用lambda x: ', '.join(x.unique())4X减速结果.set在这些数据上使用是一些更快的削减,但它确实取决于.

# @jpp

%%timeit
v = df.groupby('Name')['Color'].apply(set).reset_index()
v['Distinct'] = v['Color'].map(len)
v['Color'] = v['Color'].map(', '.join)

219 ms ± 1.83 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Run Code Online (Sandbox Code Playgroud)

# @jezrael

%%timeit
(df.groupby('Name')['Color'].agg(['nunique', lambda x: ', '.join(set(x))])
        .rename(columns={'nunique':'Distinct', '<lambda>':'Values'})
        .reset_index())

118 ms ± 4.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

性能随数据变化很大,您可能希望在决定使用什么之前为所有解决方案计算自己的数据.

  • @shakedzy嗯,我通过观察其他用户回答类似问题来学习:)经验法则是支持最常用的功能:均值,总和,最大值,最小值,大小,计数,单数......等等.这不是一个详尽的清单. (2认同)