避免for循环从pandas中的其他列设置列值

时间:2019-05-24 13:12:13

标签: python pandas

我想在一个名为'new_col'的新列中分配一个csv,就像其他列的值的字符串一样。

目前,我的工作如下:

df['new_col'] = (df['a'].map(str) + ',' + df['b'].map(str))

这工作得很好,但我希望它能够自治。我想向函数提供一个列列表,然后让它执行字符串。

我当然可以如下遍历列表:

lstColumns = ['a','b']
lstItems = []

for item in lstColumns:
    lstItems.append(df[item])
szChain = (',').join(lstItems)

但这很丑陋,我可能会在具有更多列的数据帧上使用它。

那么有什么方法可以简化吗?

4 个答案:

答案 0 :(得分:0)

您可以使用以下内容:

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

答案 1 :(得分:0)

向数据框逐行(轴= 1)应用功能。 该函数映射到字符串并以“,”

连接
cols = ["a", "b"]
df.apply(lambda x: ", ".join(map(str, x[cols])), axis=1)                                                                                        

答案 2 :(得分:0)

您可以使用@Anshul Jindal提出的版本,但是还有另一种选择,它的输出差异很大,如果数据中有nan,则可能会有用。

import io

df = pd.DataFrame({'a': ['a', 'b', np.nan], 
                   'b': [np.nan, 'e', 'f'], 
                   'c': ['g', 'h', 'i'], 
                   'd': ['j', np.nan, 'l']})
cols = ['a', 'b' ,'d']

# another approach, using temporary text buffer
with io.StringIO() as output:
    df[cols].to_csv(output, sep=',', index=False, header=False)
    output.seek(0)
    df = df.assign(new_col=output.readlines())

df.new_col = df.new_col.str.strip()

# approach proposed earlier
df = df.assign(new_col_2 = df[cols].apply(
    lambda x: ','.join(x.dropna().astype(str)),
    axis=1
))

print(df)
     a    b  c    d new_col new_col_2
0    a  NaN  g    j    a,,j       a,j
1    b    e  h  NaN    b,e,       b,e
2  NaN    f  i    l    ,f,l       f,l

加上非常令人惊讶的方法时机:

import io
import timeit

df = pd.DataFrame({'a': ['a', 'b', np.nan], 
                   'b': [np.nan, 'e', 'f'], 
                   'c': ['g', 'h', 'i'], 
                   'd': ['j', np.nan, 'l']})
cols = ['a', 'b' ,'d']

def buffer_approach(df, cols_to_merge):
    with io.StringIO() as output:
        df[cols_to_merge].to_csv(output, sep=',', index=False, header=False)
        output.seek(0)
        df = df.assign(new_col=output.readlines())

    df.new_col = df.new_col.str.strip()
    return df

def pandas_approach(df, cols_to_merge):
    df = df.assign(new_col = df[cols_to_merge].apply(
        lambda x: ','.join(x.dropna().astype(str)),
        axis=1
    ))
    return df

print(timeit.repeat("buffer_approach(df, cols)", globals=globals(), repeat=5, number=1000))
print(timeit.repeat("pandas_approach(df, cols)", globals=globals(), repeat=5, number=1000))

[2.5745794447138906, 2.556944037321955, 2.5482078031636775, 2.2512022089213133, 2.0038619451224804]
[3.6452969149686396, 3.326099018100649, 3.5136850751005113, 3.9479835461825132, 3.4149401267059147]

答案 3 :(得分:-1)

也许我不能正确理解您的问题,但是如果您有很多专栏,可以这样做:

cols_a = ['a1', 'a2', 'a3']
cols_b = ['b1', 'b2', 'b3']
cols_res = ['res1', 'res2', 'res3']

df = pd.DataFrame({i:[i, i] for i in (cols_a+cols_b+ cols_res)})

print(df)
   a1  a2  a3  b1  b2  b3  res1  res2  res3
0  a1  a2  a3  b1  b2  b3  res1  res2  res3
1  a1  a2  a3  b1  b2  b3  res1  res2  res3

df[cols_res] = (df[cols_a].astype(str).values + ',' + df[cols_b].astype(str).values)

print(df)
   a1  a2  a3  b1  b2  b3   res1   res2   res3
0  a1  a2  a3  b1  b2  b3  a1,b1  a2,b2  a3,b3
1  a1  a2  a3  b1  b2  b3  a1,b1  a2,b2  a3,b3