Если капитализация ваших NaN
s не имеет значения, этого будет достаточно:
df['concatenated'] = df.astype(str).apply('_'.join,1)
>>> df
v1 v2 v3 concatenated
0 2.0 NaN 1.0 2.0_nan_1.0
1 1.0 1.0 1.0 1.0_1.0_1.0
2 NaN NaN 2.0 nan_nan_2.0
3 NaN NaN NaN nan_nan_nan
4 NaN NaN 2.0 nan_nan_2.0
Если капитализация имеет значение, то вы должны заранее использовать replace
:
df['concatenated'] = df.astype(str).replace('nan','NaN').apply('_'.join,1)
>>> df
v1 v2 v3 concatenated
0 2.0 NaN 1.0 2.0_NaN_1.0
1 1.0 1.0 1.0 1.0_1.0_1.0
2 NaN NaN 2.0 NaN_NaN_2.0
3 NaN NaN NaN NaN_NaN_NaN
4 NaN NaN 2.0 NaN_NaN_2.0