如何在pandas中合并/组合列?

时间:2017-10-04 11:35:36

标签: python pandas dataframe merge multiple-columns

我有一个包含4列的(example-)数据框:

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

感谢您的帮助。

5 个答案:

答案 0 :(得分:6)

选项1
使用assigndrop

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 :(得分:2)

书面问题要求合并/合并而不是总和,因此将其发布以帮助找到此答案的人们在使用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()在索引上对齐,因此您需要将set_index()附加到每个df引用上。

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

答案 2 :(得分:1)

使用difference表示没有{ "id":"0552065465", "name":"james" . . . } 的列名,然后获取Asum

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

答案 3 :(得分:0)

您也可以将ffilliloc一起使用:

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

答案 4 :(得分:0)

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