将多列值合并为一个列在Python Pandas中

95

我有一个这样的Pandas数据框:

   Column1  Column2  Column3  Column4  Column5
 0    a        1        2        3        4
 1    a        3        4        5
 2    b        6        7        8
 3    c        7        7        
我现在想做的是获取一个新的数据框,其中包含Column1和一个新的columnA。这个columnA应该包含从第2列到第n列(其中n是从Column2到行末的列数)的所有值,如下所示:
  Column1  ColumnA
0   a      1,2,3,4
1   a      3,4,5
2   b      6,7,8
3   c      7,7

我应该如何最好地解决这个问题?

4个回答

157

您可以调用apply并传递axis=1以逐行应用,然后将dtype转换为strjoin

In [153]:
df['ColumnA'] = df[df.columns[1:]].apply(
    lambda x: ','.join(x.dropna().astype(str)),
    axis=1
)
df

Out[153]:
  Column1  Column2  Column3  Column4  Column5  ColumnA
0       a        1        2        3        4  1,2,3,4
1       a        3        4        5      NaN    3,4,5
2       b        6        7        8      NaN    6,7,8
3       c        7        7      NaN      NaN      7,7

在这里我调用 dropna 来去除 NaN,但是我们需要再次转换为 int ,以免最终得到的结果为浮点型字符串。


由于某些原因,这对我不起作用。我得到了重复的结果。因此,第0行列A是1、2、3、4、1、2、3、4。 - Sade
1
看起来使用 iloc 对我很有效。没有重复项。df ['ColumnA'] = df.iloc [:,source_col_loc + 1:source_col_loc + 4] .apply( lambda x:“,”.join(x.astype(str)),axis = 1) - Sade
一个值正在尝试设置在DataFrame的切片副本上。 请尝试使用.loc[row_indexer,col_indexer] = value。 - Kaustuv
对于未来的访问者,如果只想合并某些列(并控制顺序),您可以将df[df.columns[1:]]替换为df[['Column4','Column1']] - undefined

23

我建议使用.assign

df2 = df.assign(ColumnA = df.Column2.astype(str) + ', ' + \
  df.Column3.astype(str) + ', ' df.Column4.astype(str) + ', ' \
  df.Column4.astype(str) + ', ' df.Column5.astype(str))

很简单,可能有点冗长,但对我很有效


2
此外,如果您正在处理大量数据,则比lambda函数更快。 - Amin Salgado

11

如果你的数据框有很多列,比如1000列,并且你想基于特定的列名合并一些列,比如问题中的Column2和该列后面的任意数量的列(在这里是Column2后面的3列,包括Column2本身)。

我们可以使用.get_loc()方法获取列的位置 - 如此处所述。

source_col_loc = df.columns.get_loc('Column2') # column position starts from 0

df['ColumnA'] = df.iloc[:,source_col_loc+1:source_col_loc+4].apply(
    lambda x: ",".join(x.astype(str)), axis=1)

df

Column1  Column2  Column3  Column4  Column5  ColumnA
0       a        1        2        3        4  1,2,3,4
1       a        3        4        5      NaN    3,4,5
2       b        6        7        8      NaN    6,7,8
3       c        7        7      NaN      NaN      7,7

要去除NaN,请使用.dropna().fillna()

希望对您有所帮助!


10

apply()比agg()慢100倍

不要使用apply,它不能很好地扩展。相反,请使用df.agg()。使用apply()需要几秒钟的时间,而agg()只需要毫秒(ms)级别的时间。

以下是一个示例:

import numpy as np
import pandas as pd

def createList(r1, r2):
    return np.arange(r1, r2+1, 1)

sample_data = createList(1, 100_000) # a list of 100,000 values

test_df = pd.DataFrame(
    [sample_data]
)

test_df.apply(lambda x: ','.join(x.astype(str))) #3.47 s ± 24.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

test_df.astype(str).agg(', '.join, axis=1) #34.8 ms ± 407 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

从这个示例中可以看出,apply()的平均时间为3.47秒,而agg()的平均时间为34.8毫秒。随着添加更多数据,性能差距将会越来越大。

* 注意,在jupyter笔记本中使用%%timeit获取每种方法的运行时间。


1
已经测试过了,我可以确认它要快得多。 - Teamothy
你能分享一个可重复的代码,将你的建议应用于多个特定列聚合吗?在你的答案中如何定义具体的列名? - bonCodigo
@bonCodigo,你能提供一个数据框的例子吗? - trey hannam
可以试试看,很高兴帮您查看一下:https://dev59.com/-9T7oIgBc1ULPQZF86JD - bonCodigo
对于那些寻求更简单的聚合函数语法的人:df['FullName'] = df[['First_Name', 'Last_Name']].agg('-'.join, axis=1) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接