首页 > 解决方案 > 带有 Apply 和 Groupby 的 Lambda

问题描述

我正在尝试计算由第二列分组的熊猫数据框的列中的唯一值,并将结果作为数据框中的新列返回。

当我在以下数据帧上测试此操作时,它返回空值。

df = pd.DataFrame([('bird', 'Falconiformes', 389.0),   ('bird', 'Psittaciformes', 24.0),   ('mammal', 'Carnivora', 80.2),   ('mammal', 'Primates', np.nan),   ('mammal', 'Carnivora', 58)],   index=['falcon', 'parrot', 'lion', 'monkey', 'leopard'],columns=('class', 'order', 'max_speed'))

在熊猫 0.18 中,我正在使用

df['test'] = df.groupby('class').transform('unique')
Traceback (most recent call last):

  File "<ipython-input-146-283294ac8bef>", line 1, in <module>
    df['test'] = df.groupby('class').transform('unique')

  File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\groupby\generic.py", line 1469, in transform
    raise ValueError(msg)

ValueError: 'unique' is not a valid function name for transform(name)

但我的管理员最近更新了 pandas 和 unique 不再是转换的有效函数。有一个线程建议申请 pandas 1.1.3(见讨论)。我查看了 1.1.3 的新文档并尝试使用以下内容

df['test']=df.groupby('class').apply(lambda x: x['max_speed'].unique())
df
Out[135]: 
     index   class           order  max_speed test
0   falcon    bird   Falconiformes      389.0  NaN
1   parrot    bird  Psittaciformes       24.0  NaN
2     lion  mammal       Carnivora       80.2  NaN
3   monkey  mammal        Primates        NaN  NaN
4  leopard  mammal       Carnivora       58.0  NaN

但 apply 不会将值扩展到其他行,即使

df.groupby('class').apply(lambda x: x['max_speed'].unique())
Out[140]: 
class
bird          [389.0, 24.0]
mammal    [80.2, nan, 58.0]
dtype: object

如果我尝试添加最新应用文档中提到的关键字,我会收到一条错误消息。

 df['test']=df.groupby('class').apply(lambda x: x['max_speed'].unique(), result_type='expand')
Traceback (most recent call last):
 File "<ipython-input-145-9b84754c6daf>", line 1, in <module>
    df['test']=df.groupby('class').apply(lambda x: x['max_speed'].unique(), result_type='expand')

  File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\groupby\groupby.py", line 870, in apply
    return self._python_apply_general(f, self._selected_obj)

  File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\groupby\groupby.py", line 892, in _python_apply_general
    keys, values, mutated = self.grouper.apply(f, data, self.axis)

  File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\groupby\ops.py", line 213, in apply
    res = f(group)

  File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\groupby\groupby.py", line 843, in f
    return func(g, *args, **kwargs)

TypeError: <lambda>() got an unexpected keyword argument 'result_type'

我知道我可以将 groupby 与聚合和唯一函数一起使用,并将生成的数据帧重新合并。但我必须为几个不同的分组执行此操作,我更喜欢单行答案。

标签: pythonpandasdataframepandas-groupbypandas-apply

解决方案


这有点老套,但我认为它可以满足您的需求

df.groupby('class').apply(lambda d: d.assign(Test = [d['max_speed'].unique()]*len(d)))

生产

|                       | class   | order          |   max_speed | Test             |
|:----------------------|:--------|:---------------|------------:|:-----------------|
| ('bird', 'falcon')    | bird    | Falconiformes  |       389   | [389.  24.]      |
| ('bird', 'parrot')    | bird    | Psittaciformes |        24   | [389.  24.]      |
| ('mammal', 'lion')    | mammal  | Carnivora      |        80.2 | [80.2  nan 58. ] |
| ('mammal', 'monkey')  | mammal  | Primates       |       nan   | [80.2  nan 58. ] |
| ('mammal', 'leopard') | mammal  | Carnivora      |        58   | [80.2  nan 58. ] |

诀窍是说服assign应该d['max_speed'].unique()在所有相关行中复制它——因为我们传递了一个长度列表,该列表对于所有条目len(d)具有相同的元素d['max_speed'].unique()。这dgroupby


推荐阅读