Python 连接数据帧中的列值,同时忽略NAN
我有一张桌子在下面 df: 现在,我正在尝试连接除第一列之外的所有列,我希望我的数据框按以下方式显示 新的"基本法":Python 连接数据帧中的列值,同时忽略NAN,python,string,pandas,dataframe,nan,Python,String,Pandas,Dataframe,Nan,我有一张桌子在下面 df: 现在,我正在尝试连接除第一列之外的所有列,我希望我的数据框按以下方式显示 新的"基本法": EVNT_ID col1 col2 col3 col4 new_col 123454 1 Nan 4 5 1|4|5 628392 Nan 3 Nan 7 3|7 293899 2 Nan Nan 6 2|6 127820 9 11 12 19 9|11|12|19 我正在使用
EVNT_ID col1 col2 col3 col4 new_col
123454 1 Nan 4 5 1|4|5
628392 Nan 3 Nan 7 3|7
293899 2 Nan Nan 6 2|6
127820 9 11 12 19 9|11|12|19
我正在使用以下代码
df['new_column'] = df[~df.EVNT_ID].apply(lambda x: '|'.join(x.dropna().astype(str).values), axis=1)
但它给了我以下的错误
输入类型不支持ufunc“invert”,并且无法根据强制转换规则安全地将输入强制为任何受支持的类型
如果有人能告诉我哪里错了,我将不胜感激。我非常感谢。您可以使用过滤器和agg:
或者
如果性能很重要,您可以使用列表:
joined = [
'|'.join([str(int(x)) for x in r if pd.notna(x)])
for r in df.iloc[:,1:].values.tolist()
]
joined
# ['1|4|5', '3|7', '2|6', '9|11|12|19']
df.assign(new_col=joined)
EVNT_ID col1 col2 col3 col4 new_col
0 123454 1.0 NaN 4.0 5 1|4|5
1 628392 NaN 3.0 NaN 7 3|7
2 293899 2.0 NaN NaN 6 2|6
3 127820 9.0 11.0 12.0 19 9|11|12|19
如果您可以原谅数据帧分配的开销,下面是两个最快解决方案的计时
df = pd.concat([df] * 1000, ignore_index=True)
# In this post.
%%timeit
[
'|'.join([str(int(x)) for x in r if pd.notna(x)])
for r in df.iloc[:,1:].values.tolist()
]
# RafaelC's answer.
%%timeit
[
'|'.join([k for k in a if k])
for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values.tolist())
]
31.9 ms ± 800 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
23.7 ms ± 409 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
尽管注意到答案并不完全相同,因为@RafaelC的代码生成浮点数:['1.0 | 2.0 | 9.0','3.0 | 11.0',…]。如果这很好,那就太好了。否则,您将需要转换为int,这将增加更多开销。您可以使用filter和agg执行此操作:
或者
如果性能很重要,您可以使用列表:
joined = [
'|'.join([str(int(x)) for x in r if pd.notna(x)])
for r in df.iloc[:,1:].values.tolist()
]
joined
# ['1|4|5', '3|7', '2|6', '9|11|12|19']
df.assign(new_col=joined)
EVNT_ID col1 col2 col3 col4 new_col
0 123454 1.0 NaN 4.0 5 1|4|5
1 628392 NaN 3.0 NaN 7 3|7
2 293899 2.0 NaN NaN 6 2|6
3 127820 9.0 11.0 12.0 19 9|11|12|19
如果您可以原谅数据帧分配的开销,下面是两个最快解决方案的计时
df = pd.concat([df] * 1000, ignore_index=True)
# In this post.
%%timeit
[
'|'.join([str(int(x)) for x in r if pd.notna(x)])
for r in df.iloc[:,1:].values.tolist()
]
# RafaelC's answer.
%%timeit
[
'|'.join([k for k in a if k])
for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values.tolist())
]
31.9 ms ± 800 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
23.7 ms ± 409 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
尽管注意到答案并不完全相同,因为@RafaelC的代码生成浮点数:['1.0 | 2.0 | 9.0','3.0 | 11.0',…]。如果这很好,那就太好了。否则,您将需要转换为int,这会增加更多开销。使用列表理解和zip 时机似乎还可以
df = pd.concat([df]*1000)
%timeit [['|'.join([k for k in a if k])] for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values)]
10.8 ms ± 568 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df.filter(like='col').agg(lambda x: x.dropna().astype(int).astype(str).str.cat(sep='|'), axis=1)
1.68 s ± 91.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit df.iloc[:, 1:].apply(lambda x: '|'.join(str(el) for el in x if str(el) != 'nan'), axis=1)
87.8 ms ± 5.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df.assign(new_col=['|'.join([str(int(x)) for x in r if ~np.isnan(x)]) for r in df.iloc[:,1:].values])
45.1 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
使用列表理解和zip 时机似乎还可以
df = pd.concat([df]*1000)
%timeit [['|'.join([k for k in a if k])] for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values)]
10.8 ms ± 568 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df.filter(like='col').agg(lambda x: x.dropna().astype(int).astype(str).str.cat(sep='|'), axis=1)
1.68 s ± 91.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit df.iloc[:, 1:].apply(lambda x: '|'.join(str(el) for el in x if str(el) != 'nan'), axis=1)
87.8 ms ± 5.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df.assign(new_col=['|'.join([str(int(x)) for x in r if ~np.isnan(x)]) for r in df.iloc[:,1:].values])
45.1 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
请尝试以下代码:
df['new_col'] = df.iloc[:, 1:].apply(lambda x:
'|'.join(str(el) for el in x if str(el) != 'nan'), axis=1)
起初,我想到的是x.dropna而不是x if strel!='南,,
但是%的时间表明dropna的工作速度要慢得多。请尝试以下代码:
df['new_col'] = df.iloc[:, 1:].apply(lambda x:
'|'.join(str(el) for el in x if str(el) != 'nan'), axis=1)
起初,我想到的是x.dropna而不是x if strel!='南,,
但是%的时间表明dropna的工作速度要慢得多。感谢您的计时!虽然这不是一个特别公平的比较,除非第一个列表comp也被分配,因为这会产生开销;这足以让事情有所不同!我的回答也反映了你的时间安排。我看到了。感谢您的投入!:}我们的答案也不完全相同。您的代码生成浮点:['1.0 | 2.0 | 9.0'、'3.0 | 11.0'、'4.0 | 12.0'、'5 | 7 | 6 | 19']感谢您的计时!虽然这不是一个特别公平的比较,除非第一个列表comp也被分配,因为这会产生开销;这足以让事情有所不同!我的回答也反映了你的时间安排。我看到了。感谢您的投入!:}我们的答案也不完全相同。您的代码生成浮点数:['1.0 | 2.0 | 9.0','3.0 | 11.0','4.0 | 12.0','5 | 7 | 6 | 19']