Reputation: 53
I have a pandas df:
A B C
1 10 11 23
2 NaN 2 15
3 NaN 3 31
4 NaN NaN 56
I want to shift the rows to the left to line up on the index as below:
A B C
1 10 11 23
2 2 15 NaN
3 3 31 NaN
4 56 NaN NaN
I have been trying to write a function that I can apply to the rows of the df. I was thinking if nan_counts = row.isnull().count()
I could use shift(-Nan_counts,axis=1)
but I am having absolutely no luck.
Upvotes: 0
Views: 1594
Reputation: 862511
Use apply
with axis=1
for row processing with dropna
:
df = df.apply(lambda x: pd.Series(x.dropna().values), 1)
print (df)
0 1 2
1 10.0 11.0 23.0
2 2.0 15.0 NaN
3 3.0 31.0 NaN
4 56.0 NaN NaN
For columns names (general solution):
print (df)
A B C D E
1 10.0 11.0 23 NaN NaN
2 NaN 2.0 15 NaN NaN
3 NaN 3.0 31 NaN NaN
4 NaN NaN 56 NaN NaN
df1 = df.apply(lambda x: pd.Series(x.dropna().values), 1)
df1.columns = df.columns[:len(df1.columns)]
df1 = df1.reindex(df.columns, axis=1)
print (df1)
A B C D E
1 10.0 11.0 23.0 NaN NaN
2 2.0 15.0 NaN NaN NaN
3 3.0 31.0 NaN NaN NaN
4 56.0 NaN NaN NaN NaN
Upvotes: 4
Reputation: 19947
For each row, use a list comprehension to keep only non-nan values and convert it as a Series. Pandas will automatically fill missing values with nan when the Serieses are combined.
df.apply(lambda x: pd.Series([e for e in x if pd.notnull(e)]), axis=1)
Out[27]:
0 1 2
1 10.0 11.0 23.0
2 2.0 15.0 NaN
3 3.0 31.0 NaN
4 56.0 NaN NaN
Upvotes: 1