如何将多个列值连接到Panda数据帧中的单个列中

Nam*_*ena 20 python dataframe pandas

这个问题与之前发布的相同.我想连接三列而不是连接两列:

这是结合两列:

df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3], 'new':['apple', 'banana', 'pear']})

df['combined']=df.apply(lambda x:'%s_%s' % (x['foo'],x['bar']),axis=1)

df
    bar foo new combined
0   1   a   apple   a_1
1   2   b   banana  b_2
2   3   c   pear    c_3
Run Code Online (Sandbox Code Playgroud)

我想用这个命令组合三个列,但它不起作用,任何想法?

df['combined']=df.apply(lambda x:'%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)
Run Code Online (Sandbox Code Playgroud)

shi*_*vsn 35

你可以简单地做:

In[17]:df['combined']=df['bar'].astype(str)+'_'+df['foo']+'_'+df['new']

In[17]:df
Out[18]: 
   bar foo     new    combined
0    1   a   apple   1_a_apple
1    2   b  banana  2_b_banana
2    3   c    pear    3_c_pear
Run Code Online (Sandbox Code Playgroud)

  • 如果任何列为“None”,则“df['combined']”将变为“nan”。示例:如果“df.new.iloc[0] == None”,则“df.combined.iloc[0]”变为“nan”,而不是“1_a_” (3认同)
  • 与更大的DF上的`.apply(,axis = 1)`1相比,这个解决方案会快得多 (2认同)
  • @MaxU是的,它非常容易. (2认同)
  • 使用此解决方案时,我收到了“SettingWithCopyWarning” - 如何避免触发该警告? (2认同)
  • 但是,当您需要加入许多列时,这会很烦人。 (2认同)

All*_*len 25

使用的另一种解决方案DataFrame.apply(),当您想加入更多的列时,键入更少,可扩展性更高:

cols = ['foo', 'bar', 'new']
df['combined'] = df[cols].apply(lambda row: '_'.join(row.values.astype(str)), axis=1)
Run Code Online (Sandbox Code Playgroud)

  • **没有 lambda** (更快、更简洁):`df[cols].astype(str).apply('_'.join, axis=1)`。也就是说,使用 `.str.cat(...).str.cat(...)...` 仍然更快。 (11认同)
  • 我遇到的一个小问题是“.values.astype(str)”将“None”转换为字符串“None”而不是空字符串。显然。 (4认同)
  • 当列列表保存为变量并且每次可以保存不同数量的列时,这是最佳解决方案 (3认同)
  • 你真是天赐之物,这个内衬解决方案如此简洁而优雅 (2认同)

Max*_*axU 9

只是想对两种解决方案进行时间比较(对于30K行DF):

In [1]: df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3], 'new':['apple', 'banana', 'pear']})

In [2]: big = pd.concat([df] * 10**4, ignore_index=True)

In [3]: big.shape
Out[3]: (30000, 3)

In [4]: %timeit big.apply(lambda x:'%s_%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)
1 loop, best of 3: 881 ms per loop

In [5]: %timeit big['bar'].astype(str)+'_'+big['foo']+'_'+big['new']
10 loops, best of 3: 44.2 ms per loop
Run Code Online (Sandbox Code Playgroud)

还有一些选择:

In [6]: %timeit big.ix[:, :-1].astype(str).add('_').sum(axis=1).str.cat(big.new)
10 loops, best of 3: 72.2 ms per loop

In [11]: %timeit big.astype(str).add('_').sum(axis=1).str[:-1]
10 loops, best of 3: 82.3 ms per loop
Run Code Online (Sandbox Code Playgroud)


cbr*_*rnr 7

如果您想合并更多的列,使用Series方法str.cat可能很方便:

df["combined"] = df["foo"].str.cat(df[["bar", "new"]].astype(str), sep="_")
Run Code Online (Sandbox Code Playgroud)

基本上,您选择第一列(如果尚未为type str,则需要添加.astype(str)),然后将其他列(由可选的分隔符分隔)添加到该列。


Jan*_*mbi 7

首先将列转换为 str。然后使用 .T.agg('_'.join) 函数将它们连接起来。更多信息可以在这里获取

# Initialize columns
cols_concat = ['first_name', 'second_name']

# Convert them to type str
df[cols_concat] = df[cols_concat].astype('str')

# Then concatenate them as follows
df['new_col'] = df[cols_concat].T.agg('_'.join)
Run Code Online (Sandbox Code Playgroud)


mil*_*.ai 6

我想你错过了一个%s

df['combined']=df.apply(lambda x:'%s_%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)
Run Code Online (Sandbox Code Playgroud)


der*_*ers 6

@allen 给出的答案相当通用,但对于较大的数据帧可能缺乏性能:

确实减少了很多更好:

from functools import reduce

import pandas as pd

# make data
df = pd.DataFrame(index=range(1_000_000))
df['1'] = 'CO'
df['2'] = 'BOB'
df['3'] = '01'
df['4'] = 'BILL'


def reduce_join(df, columns):
    assert len(columns) > 1
    slist = [df[x].astype(str) for x in columns]
    return reduce(lambda x, y: x + '_' + y, slist[1:], slist[0])


def apply_join(df, columns):
    assert len(columns) > 1
    return df[columns].apply(lambda row:'_'.join(row.values.astype(str)), axis=1)

# ensure outputs are equal
df1 = reduce_join(df, list('1234'))
df2 = apply_join(df, list('1234'))
assert df1.equals(df2)

# profile
%timeit df1 = reduce_join(df, list('1234'))  # 733 ms
%timeit df2 = apply_join(df, list('1234'))   # 8.84 s

Run Code Online (Sandbox Code Playgroud)


kra*_*ski 6

可能最快的解决方案是在纯 Python 中操作:

Series(
    map(
        '_'.join,
        df.values.tolist()
        # when non-string columns are present:
        # df.values.astype(str).tolist()
    ),
    index=df.index
)
Run Code Online (Sandbox Code Playgroud)

与@MaxU 答案的比较(使用big具有数字和字符串列的数据框):

%timeit big['bar'].astype(str) + '_' + big['foo'] + '_' + big['new']
# 29.4 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)


%timeit Series(map('_'.join, big.values.astype(str).tolist()), index=big.index)
# 27.4 ms ± 2.36 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

与@derchambers 答案的比较(使用他们的df数据框,其中所有列都是字符串):

from functools import reduce

def reduce_join(df, columns):
    slist = [df[x] for x in columns]
    return reduce(lambda x, y: x + '_' + y, slist[1:], slist[0])

def list_map(df, columns):
    return Series(
        map(
            '_'.join,
            df[columns].values.tolist()
        ),
        index=df.index
    )

%timeit df1 = reduce_join(df, list('1234'))
# 602 ms ± 39 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df2 = list_map(df, list('1234'))
# 351 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Run Code Online (Sandbox Code Playgroud)