首页 > 解决方案 > 转换 pandas DataFrames 组 - 完全,而不仅仅是一个系列

问题描述

我想转换熊猫数据框中的每个组。组我的意思不是 DataFrame 的单个列,而是整个组。这是我的意思的一个例子:

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar'],
                   'B' : ['one', 'one', 'two', 'two', 'one', 'two'],
                   'C' : [    1,     5,     5,     2,     6,     5],
                   'D' : [  2.0,    5.,    8.,    1.,     2.,   9.]})

def transformation_function(group: pd.DataFrame) -> pd.DataFrame:
    group = group.copy()
    if all(group.B == 'one'):
        group.D[group.C>2] = group.D[group.C>2] + 1
    else:
        group.A = 'new'
    return group

df.groupby('B').transform(transformation_function)

我期望的地方

     pd.DataFrame({'A' : ['foo', 'bar', 'new', 'new', 'foo', 'new'],
                   'B' : ['one', 'one', 'two', 'two', 'one', 'two'],
                   'C' : [    1,     5,     5,     2,     5,     5],
                   'D' : [  2.0,    6.,    8.,    1.,    3.,    9.]})

因此。现在,我得到了

AttributeError:“系列”对象没有属性“B”

这对我来说没有意义,因为文档明确指出

调用函数在每个组上生成一个类似索引的 DataFrame,并返回一个与填充了转换值的原始对象具有相同索引的 DataFrame

我知道所有示例都是基于系列的,例如df.groupby('B')['a_column_name'].transform(change_fct),但是如果需要转换函数的所有列,则无法进行类似的操作。

那么,如何使用 pandas 的方法链获得我的期望呢?

标签: pythonpandasdataframemethod-chaining

解决方案


在您的解决方案transform函数中分别处理每一列,因此无法按名称选择列。需要GroupBy.apply

df = df.groupby('B').apply(transformation_function)
    
print (df)
         A    B  C    D
B                      
one 0  foo  one  1  2.0
    1  bar  one  5  6.0
    4  foo  one  6  3.0
two 2  new  two  5  8.0
    3  new  two  2  1.0
    5  new  two  5  9.0

处理组如何可能参见例如print

df.groupby('B').transform(lambda x: print (x))
0    foo
1    bar
4    foo
Name: A, dtype: object
0    1
1    5
4    6
Name: C, dtype: int64
0    2.0
1    5.0
4    2.0
Name: D, dtype: float64
     A  C    D
0  foo  1  2.0
1  bar  5  5.0
4  foo  6  2.0
2    foo
3    bar
5    bar
Name: A, dtype: object
2    5
3    2
5    5
Name: C, dtype: int64
2    8.0
3    1.0
5    9.0
Name: D, dtype: float64
     A  C    D
2  foo  5  8.0
3  bar  2  1.0
5  bar  5  9.0

df.groupby('B').apply(lambda x: print (x))

     A    B  C    D
0  foo  one  1  2.0
1  bar  one  5  5.0
4  foo  one  6  2.0
     A    B  C    D
2  foo  two  5  8.0
3  bar  two  2  1.0
5  bar  two  5  9.0

推荐阅读