0

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.

3 Answers 3

1

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]
Sign up to request clarification or add additional context in comments.

1 Comment

This worked perfectly with way better performance! Thanks
1

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]

1 Comment

What's the performance on this (and in general using apply) vs the accepted answer?
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.