转换 pandas 个 DataFrames 组 - 完全转换,而不仅仅是一个系列
Transform pandas DataFrames groups - completely, not just a Series
我想转换 pandas' DataFrame 中的每个组。按组,我指的不是 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: 'Series' object has no attribute 'B'
这对我来说没有意义,因为 documentation 明确指出
Call function producing a like-indexed DataFrame on each group and return a DataFrame having the same indexes as the original object filled with the transformed values
我知道所有示例都是基于系列的,例如 df.groupby('B')['a_column_name'].transform(change_fct)
,但是如果转换函数需要所有列,那么这样的事情是不可能的。
那么,如何使用 pandas' 方法链获得我期望的结果?
在您的解决方案中,transform
函数分别处理每一列,因此不可能 select 按名称列。需要 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
我想转换 pandas' DataFrame 中的每个组。按组,我指的不是 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: 'Series' object has no attribute 'B'
这对我来说没有意义,因为 documentation 明确指出
Call function producing a like-indexed DataFrame on each group and return a DataFrame having the same indexes as the original object filled with the transformed values
我知道所有示例都是基于系列的,例如 df.groupby('B')['a_column_name'].transform(change_fct)
,但是如果转换函数需要所有列,那么这样的事情是不可能的。
那么,如何使用 pandas' 方法链获得我期望的结果?
在您的解决方案中,transform
函数分别处理每一列,因此不可能 select 按名称列。需要 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