Reputation: 1581
I have a dataframe like the following:
List1 List2 List3 List4 List5 List6 List7 List8
0 NaN NaN 1 NaN NaN NaN 1 NaN
1 NaN NaN 1 NaN NaN NaN 1 NaN
2 NaN NaN 1 NaN 1.0 NaN 1 NaN
3 NaN NaN 1 NaN NaN NaN 1 NaN
4 NaN NaN 1 NaN 1.0 NaN 1 NaN
I want to create a new Column called Lists
which is an array of all the other columns with a non null value. ie:
Lists
0 ['List3', 'List7']
1 ['List3', 'List7']
2 ['List3', 'List5', 'List7']
3 ['List3', 'List7']
4 ['List3', 'List5', 'List7']
I accomplished this with an iterrows()
loop, but it's not performant at all. Would appreciate any ideas here.
Upvotes: 0
Views: 578
Reputation: 195438
Another version:
df["Lists"] = df.apply(lambda x: x[x.notna()].index.tolist(), axis=1)
print(df)
Prints:
List1 List2 List3 List4 List5 List6 List7 List8 Lists
0 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
1 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
2 NaN NaN 1 NaN 1.0 NaN 1 NaN [List3, List5, List7]
3 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
4 NaN NaN 1 NaN 1.0 NaN 1 NaN [List3, List5, List7]
Upvotes: 1
Reputation: 42916
We can use DataFrame.dot
to get all columns which are notna
:
df["Lists"] = df.notna().dot(df.columns+",").str.rstrip(",").str.split(",")
List1 List2 List3 List4 List5 List6 List7 List8 Lists
0 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
1 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
2 NaN NaN 1 NaN 1.00 NaN 1 NaN [List3, List5, List7]
3 NaN NaN 1 NaN NaN NaN 1 NaN [List3, List7]
4 NaN NaN 1 NaN 1.00 NaN 1 NaN [List3, List5, List7]
Upvotes: 1
Reputation: 18416
You can use pandas.DataFrame.apply
on axis=1
with a lambda with a list-comprehension and take only the columns that has non-NaN
value for each row using pd.notna()
:
>>> df.apply(lambda x: [c for c in df if pd.notna(x[c])], axis=1)
0 [List3, List7]
1 [List3, List7]
2 [List3, List5, List7]
3 [List3, List7]
4 [List3, List5, List7]
dtype: object
Upvotes: 0