Reputation: 2017
I have a dataframe df1 that looks like this:
Z1 Z2 Z3 Z4
0 0 A A
0 B 0 0
C 0 C 0
D 0 D 0
0 0 E 0
I want to make a new dataframe df2 that looks like this:
Z1 Z2 Z3 Z4
C B A A
D C
D
E
For that I am declaring a blank dataframe df2
which has column Z1 Z2 Z3 Z4
.
I am doing so with the help of for loop which is as follows:
periods=['Z1', 'Z2', 'Z3', 'Z4']
for i in periods:
for j in range(0,len(df1)):
if df1.loc[j:j,i:i]!=0:
#I want to write such that non zero value will be written in df2
#Like
#df2[something]=df1.loc[j:j,i:i]
But the length of df2
is 0 as of yet, and so I can't access its cells by indexing, and I am not able to sort out how to put values into df2
.
Note:This question is different from the one marked as duplicate my explanation for same is in comments
Upvotes: 0
Views: 242
Reputation: 164833
This is one way.
df = pd.DataFrame({k: pd.Series(list(filter(None, df[k]))) for k in df}).fillna('')
# Z1 Z2 Z3 ZR
# 0 C B A A
# 1 D C
# 2 D
# 3 E
# 4
This may be more efficient than lambda
for larger dataframes.
Upvotes: 1
Reputation: 5225
You can accomplish this by using pd.DataFrame.apply
with pd.Series
+ a list comprehension:
df.apply(lambda x: pd.Series([i for i in x if i != '0']))
# Z1 Z2 Z3 Z4
# 0 C B A A
# 1 D NaN C NaN
# 2 NaN NaN D NaN
# 3 NaN NaN E NaN
If you'd rather have empty strings thanNaN
, add a call to .fillna
:
df.apply(lambda x: pd.Series([i for i in x if i != '0'])).fillna('')
# Z1 Z2 Z3 Z4
# 0 C B A A
# 1 D C
# 2 D
# 3 E
Upvotes: 1
Reputation: 323376
Is this what you need ?
df.replace('0',np.nan).apply(lambda x: sorted(x,key=pd.isnull)).dropna(thresh=1).fillna('')
Out[681]:
Z1 Z2 Z3 Z4
0 C B A A
1 D C
2 D
3 E
Upvotes: 1