合并 DataFrame 中的重复列
Posted
技术标签:
【中文标题】合并 DataFrame 中的重复列【英文标题】:Combine duplicated columns within a DataFrame 【发布时间】:2012-10-16 05:40:38 【问题描述】:如果我有一个包含相同名称的列的数据框,有没有办法将具有相同名称的列与某种函数(即 sum)结合起来?
例如:
In [186]:
df["NY-WEB01"].head()
Out[186]:
NY-WEB01 NY-WEB01
DateTime
2012-10-18 16:00:00 5.6 2.8
2012-10-18 17:00:00 18.6 12.0
2012-10-18 18:00:00 18.4 12.0
2012-10-18 19:00:00 18.2 12.0
2012-10-18 20:00:00 19.2 12.0
如何通过对列名相同的每一行求和来折叠 NY-WEB01 列(有一堆重复的列,而不仅仅是 NY-WEB01)?
【问题讨论】:
是的,这是Split-Apply-Combine,您的聚合函数是sum()
。这是一个非常普遍的范式。顺便说一句,您是在“聚合”行,而不是“合并”它们。
另外,这里实际上是在组合行,而不是列。 (您正在根据具有相同值(不是“名称”)的某些列组合行)。您可能想更正您的标题。
【参考方案1】:
我相信这可以满足您的需求:
df.groupby(lambda x:x, axis=1).sum()
或者,根据 df 的长度,速度提高 3% 到 15%:
df.groupby(df.columns, axis=1).sum()
编辑:要将其扩展到总和之外,请使用 .agg()
(.aggregate()
的缩写):
df.groupby(df.columns, axis=1).agg(numpy.max)
【讨论】:
是否可以仅针对特定列(具有重复的列名)?原因是如果某列被标识为Timestamp
,pandas 会报错TypeError: Addition/subtraction of integers and integer-arrays with Timestamp is no longer supported.
【参考方案2】:
熊猫 >= 0.20: df.groupby(level=0, axis=1)
这里不需要 lambda,也不需要显式查询 df.columns
; groupby
接受 level
参数,您可以与 axis
参数一起指定。这更干净,IMO。
# Setup
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('AABBB'))
df
A A B B B
0 44 47 0 3 3
1 39 9 19 21 36
2 23 6 24 24 12
3 1 38 39 23 46
4 24 17 37 25 13
df.groupby(level=0, axis=1).sum()
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
处理MultiIndex
列
另一个需要考虑的情况是在处理MultiIndex
列时。考虑
df.columns = pd.MultiIndex.from_arrays([['one']*3 + ['two']*2, df.columns])
df
one two
A A B B B
0 44 47 0 3 3
1 39 9 19 21 36
2 23 6 24 24 12
3 1 38 39 23 46
4 24 17 37 25 13
要跨上层执行聚合,请使用
df.groupby(level=1, axis=1).sum()
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
或者,如果仅按上层聚合,则使用
df.groupby(level=[0, 1], axis=1).sum()
one two
A B B
0 91 0 6
1 48 19 57
2 29 24 36
3 39 39 69
4 41 37 38
替代解释:删除重复的列
如果您来这里是想了解如何简单地删除重复列(不执行任何聚合),请使用Index.duplicated
:
df.loc[:,~df.columns.duplicated()]
A B
0 44 0
1 39 19
2 23 24
3 1 39
4 24 37
或者,要保留最后一个,请指定keep='last'
(默认为'first'
),
df.loc[:,~df.columns.duplicated(keep='last')]
A B
0 47 3
1 9 36
2 6 12
3 38 46
4 17 13
上述两种解决方案的groupby
替代方案分别是 df.groupby(level=0, axis=1).first()
和... .last()
。
【讨论】:
【参考方案3】:对于常见的聚合函数,如sum
、mean
、median
、max
、min
、std
,这是可能的更简单的解决方案 - 仅使用参数 axis=1
处理列和 @987654329 @:
#coldspeed samples
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('AABBB'))
print (df)
print (df.sum(axis=1, level=0))
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
df.columns = pd.MultiIndex.from_arrays([['one']*3 + ['two']*2, df.columns])
print (df.sum(axis=1, level=1))
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
print (df.sum(axis=1, level=[0,1]))
one two
A B B
0 91 0 6
1 48 19 57
2 29 24 36
3 39 39 69
4 41 37 38
类似它适用于索引,然后使用axis=0
而不是axis=1
:
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('ABCDE'), index=list('aabbc'))
print (df)
A B C D E
a 44 47 0 3 3
a 39 9 19 21 36
b 23 6 24 24 12
b 1 38 39 23 46
c 24 17 37 25 13
print (df.min(axis=0, level=0))
A B C D E
a 39 9 0 3 3
b 1 6 24 23 12
c 24 17 37 25 13
df.index = pd.MultiIndex.from_arrays([['bar']*3 + ['foo']*2, df.index])
print (df.mean(axis=0, level=1))
A B C D E
a 41.5 28.0 9.5 12.0 19.5
b 12.0 22.0 31.5 23.5 29.0
c 24.0 17.0 37.0 25.0 13.0
print (df.max(axis=0, level=[0,1]))
A B C D E
bar a 44 47 19 21 36
b 23 6 24 24 12
foo b 1 38 39 23 46
c 24 17 37 25 13
如果需要使用first
、last
、size
、count
等其他函数,则必须使用coldspeed answer
【讨论】:
以上是关于合并 DataFrame 中的重复列的主要内容,如果未能解决你的问题,请参考以下文章
基于Pandas.Dataframe中的多个列合并多个重复行
合并具有来自两个不同列的匹配值的 DataFrame - Pandas [重复]