我有一个数据帧,其中包含类似以下的列:
['id','name','foo1', 'foo1', 'foo1', 'foo2','foo2', 'foo3']
我想要一个新的数据框,其中共享相同名称的列被平均:['id','name','foo1', 'foo2','foo3']
这里的列foo1将是原始数据框中名为foo1的三列的平均值,foo2将是名为foo2和foo3的两列的平均值,而foo3将保持不变。
注意:id和name不是数字类型,我必须保留它们。
我有一个数据帧,其中包含类似以下的列:
['id','name','foo1', 'foo1', 'foo1', 'foo2','foo2', 'foo3']
我想要一个新的数据框,其中共享相同名称的列被平均:['id','name','foo1', 'foo2','foo3']
这里的列foo1将是原始数据框中名为foo1的三列的平均值,foo2将是名为foo2和foo3的两列的平均值,而foo3将保持不变。
注意:id和name不是数字类型,我必须保留它们。
基本思想是按列名分组,并对每个组执行平均操作。
我看到了一些评论并尝试为您提供不同的方法来实现目标。 (解决方案(3)是我发现的最佳解决方案!)
(1)快速解决方案。 如果您只有非常有限的非数字列,并且拥有唯一的名称,例如,列id
和name
。 您可以执行以下操作:
首先设置索引['id', 'name']
以保留它们,
df = df.set_index(['id', 'name'])
然后使用DataFrame.groupby
函数对columns
进行分组,设置axis=1
(迭代每列),对每个组应用mean
函数。
df.groupby(by=df.columns, axis=1).mean()
最后,重置索引以恢复['id','name']
列。
df = df.reset_index()
这里是一个示例代码:
In [35]: df = pd.DataFrame([['001', 'a', 1, 10, 100, 1000], ['002', 'b', 2, 20, 200, 2000]], columns=['id', 'name', 'c1', 'c2', 'c2', 'c3'], index=list('AB'))
In [36]: df = df.set_index(['id', 'name'])
In [37]: df = df.groupby(by=df.columns, axis=1).mean()
In [38]: df = df.reset_index()
In [39]: df
Out[39]:
id name c1 c2 c3
0 001 a 1 55 1000
1 002 b 2 110 2000
(2) 完整解决方案。如果您有许多非数值且命名唯一的列,您可以执行以下操作:
首先,将数据框转置,
df2 = df.transpose()
然后进行分组操作(根据其索引和 axis=0
),但要小心处理每个分组:对于这些数字分组,返回它们的平均值;而对于这些非数字分组,返回它们的第一行:
df2 = df2.groupby(by=df2.index, axis=0).apply(lambda g: g.mean() if isinstance(g.iloc[0,0], numbers.Number) else g.iloc[0])
最后,将其转换回去:
df = df2.transpose()
这里是代码示例:
In [98]: df = pd.DataFrame([['001', 'a', 1, 10, 100, 1000], ['002', 'b', 2, 20, 200, 2000]], columns=['id', 'name', 'c1', 'c2', 'c2', 'c3'], index=list('AB'))
In [99]: df2 = df.transpose()
In [100]: df2 = df2.groupby(by=df2.index, axis=0).apply(lambda g: g.mean() if isinstance(g.iloc[0,0], numbers.Number) else g.iloc[0])
In [101]: df3 = df2.transpose()
In [102]: df3
Out[102]:
c1 c2 c3 id name
A 1 55 1000 001 a
B 2 110 2000 002 b
In [103]: df
Out[103]:
id name c1 c2 c2 c3
A 001 a 1 10 100 1000
B 002 b 2 20 200 2000
你需要import numbers
更多说明:
(3) 全部都在这里!这个解决方案是我找到的最佳方案:
df.groupby(by=df.columns, axis=1).apply(lambda g: g.mean(axis=1) if isinstance(g.iloc[0,0], numbers.Number) else g.iloc[:,0])
我尝试为未转置的组处理每个组,也就是说:
df.groupby(by=df.columns, axis=1).apply(gf)
并且
gf = lambda g: g.mean(axis=1) if isinstance(g.iloc[0,0], numbers.Number) else g.iloc[:,0]
我以前失败了,因为我没有仔细设置轴。你必须为mean
函数设置axis=1
,并且对于非数字组返回列。
谢谢!