如何合并/组合熊猫中的列?
Posted
技术标签:
【中文标题】如何合并/组合熊猫中的列?【英文标题】:How to merge/combine columns in pandas? 【发布时间】:2018-03-15 18:52:36 【问题描述】:我有一个包含 4 列的(示例)数据框:
data = 'A': ['a', 'b', 'c', 'd', 'e', 'f'],
'B': [42, 52, np.nan, np.nan, np.nan, np.nan],
'C': [np.nan, np.nan, 31, 2, np.nan, np.nan],
'D': [np.nan, np.nan, np.nan, np.nan, 62, 70]
df = pd.DataFrame(data, columns = ['A', 'B', 'C', 'D'])
A B C D
0 a 42.0 NaN NaN
1 b 52.0 NaN NaN
2 c NaN 31.0 NaN
3 d NaN 2.0 NaN
4 e NaN NaN 62.0
5 f NaN NaN 70.0
我现在想将 B、C 和 D 列合并/组合到新的 E 列,如下例所示:
data2 = 'A': ['a', 'b', 'c', 'd', 'e', 'f'],
'E': [42, 52, 31, 2, 62, 70]
df2 = pd.DataFrame(data2, columns = ['A', 'E'])
A E
0 a 42
1 b 52
2 c 31
3 d 2
4 e 62
5 f 70
我发现了一个非常相似的问题here,但这会在 A 列的末尾添加合并的列 B、C 和 D:
0 a
1 b
2 c
3 d
4 e
5 f
6 42
7 52
8 31
9 2
10 62
11 70
dtype: object
感谢您的帮助。
【问题讨论】:
如果 B 和 C 都有值会发生什么?您打算在 E 中保留哪一个? 好问题 - jezrael 的第二个选项进一步说明了这个问题。 【参考方案1】:对没有A
的列名使用difference
,然后得到sum
或max
:
cols = df.columns.difference(['A'])
df['E'] = df[cols].sum(axis=1).astype(int)
# df['E'] = df[cols].max(axis=1).astype(int)
df = df.drop(cols, axis=1)
print (df)
A E
0 a 42
1 b 52
2 c 31
3 d 2
4 e 62
5 f 70
如果每行有多个值:
data = 'A': ['a', 'b', 'c', 'd', 'e', 'f'],
'B': [42, 52, np.nan, np.nan, np.nan, np.nan],
'C': [np.nan, np.nan, 31, 2, np.nan, np.nan],
'D': [10, np.nan, np.nan, np.nan, 62, 70]
df = pd.DataFrame(data, columns = ['A', 'B', 'C', 'D'])
print (df)
A B C D
0 a 42.0 NaN 10.0
1 b 52.0 NaN NaN
2 c NaN 31.0 NaN
3 d NaN 2.0 NaN
4 e NaN NaN 62.0
5 f NaN NaN 70.0
cols = df.columns.difference(['A'])
df['E'] = df[cols].apply(lambda x: ', '.join(x.dropna().astype(int).astype(str)), 1)
df = df.drop(cols, axis=1)
print (df)
A E
0 a 42, 10
1 b 52
2 c 31
3 d 2
4 e 62
5 f 70
【讨论】:
【参考方案2】:选项 1
使用assign
和drop
In [644]: cols = ['B', 'C', 'D']
In [645]: df.assign(E=df[cols].sum(1)).drop(cols, 1)
Out[645]:
A E
0 a 42.0
1 b 52.0
2 c 31.0
3 d 2.0
4 e 62.0
5 f 70.0
选项 2
使用赋值和drop
In [648]: df['E'] = df[cols].sum(1)
In [649]: df = df.drop(cols, 1)
In [650]: df
Out[650]:
A E
0 a 42.0
1 b 52.0
2 c 31.0
3 d 2.0
4 e 62.0
5 f 70.0
选项 3 最近,我喜欢第 3 个选项。
使用groupby
In [660]: df.groupby(np.where(df.columns == 'A', 'A', 'E'), axis=1).first() #or sum max min
Out[660]:
A E
0 a 42.0
1 b 52.0
2 c 31.0
3 d 2.0
4 e 62.0
5 f 70.0
In [661]: df.columns == 'A'
Out[661]: array([ True, False, False, False], dtype=bool)
In [662]: np.where(df.columns == 'A', 'A', 'E')
Out[662]:
array(['A', 'E', 'E', 'E'],
dtype='|S1')
【讨论】:
选项 1 效果很好。我倾向于选择opt。 1 并选择。 2,很可能是因为它们的简单性......谢谢!【参考方案3】:书面问题要求合并/组合而不是求和,因此发布此问题是为了帮助找到此答案的人们寻求与 combine_first 合并的帮助,这可能有点棘手。
df2 = pd.concat([df["A"],
df["B"].combine_first(df["C"]).combine_first(df["D"])],
axis=1)
df2.rename(columns="B":"E", inplace=True)
A E
0 a 42.0
1 b 52.0
2 c 31.0
3 d 2.0
4 e 62.0
5 f 70.0
这有什么难的?在这种情况下没有问题 - 但假设您从不同的数据帧中提取 B、C 和 D 值,其中存在 a、b、c、d、e、f 标签,但不一定以相同的顺序。 combine_first() 与索引对齐,因此您需要在每个 df 引用上添加 set_index()。
df2 = pd.concat([df.set_index("A", drop=False)["A"],
df.set_index("A")["B"]\
.combine_first(df.set_index("A")["C"])\
.combine_first(df.set_index("A")["D"]).astype(int)],
axis=1).reset_index(drop=True)
df2.rename(columns="B":"E", inplace=True)
A E
0 a 42
1 b 52
2 c 31
3 d 2
4 e 62
5 f 70
【讨论】:
这个答案适用于字符串,而不仅仅是数字(不像那些使用sum()
的)。【参考方案4】:
您也可以将ffill
与iloc
一起使用:
df['E'] = df.iloc[:, 1:].ffill(1).iloc[:, -1].astype(int)
df = df.iloc[:, [0, -1]]
print(df)
A E
0 a 42
1 b 52
2 c 31
3 d 2
4 e 62
5 f 70
【讨论】:
【参考方案5】:Zero 使用 groupby
的第三个选项需要 numpy 导入,并且只处理要折叠的列集之外的一列,而 jpp 使用 ffill
的答案要求您知道列的排序方式。这是一个没有额外依赖项的解决方案,采用任意输入数据框,并且仅当这些列中的所有行都是单值时才折叠列:
import pandas as pd
data = ['A':'a', 'B':42, 'messy':'z',
'A':'b', 'B':52, 'messy':'y',
'A':'c', 'C':31,
'A':'d', 'C':2, 'messy':'w',
'A':'e', 'D':62, 'messy':'v',
'A':'f', 'D':70, 'messy':['z']]
df = pd.DataFrame(data)
cols = ['B', 'C', 'D']
new_col = 'E'
if df[cols].apply(lambda x: len(x.notna().value_counts()) == 1, axis=1).all():
df[new_col] = df[cols].ffill(axis=1).dropna(axis=1)
df2 = df.drop(columns=cols)
print(df, '\n\n', df2)
输出:
A B messy C D
0 a 42.0 z NaN NaN
1 b 52.0 y NaN NaN
2 c NaN NaN 31.0 NaN
3 d NaN w 2.0 NaN
4 e NaN v NaN 62.0
5 f NaN [z] NaN 70.0
A messy E
0 a z 42.0
1 b y 52.0
2 c NaN 31.0
3 d w 2.0
4 e v 62.0
5 f [z] 70.0
【讨论】:
以上是关于如何合并/组合熊猫中的列?的主要内容,如果未能解决你的问题,请参考以下文章