Transfer multiple columns string values to numbers in Pandas - python

I'm working at a data frame like this:
id type1 type2 type3
0 1 dog NaN NaN
1 2 cat NaN NaN
2 3 dog cat NaN
3 4 cow NaN NaN
4 5 dog NaN NaN
5 6 cat NaN NaN
6 7 cat dog cow
7 8 dog NaN NaN
How can I transfer it to the following dataframe? Thank you.
id dog cat cow
0 1 1.0 NaN NaN
1 2 NaN 1.0 NaN
2 3 1.0 1.0 NaN
3 4 NaN NaN 1.0
4 5 1.0 NaN NaN
5 6 NaN 1.0 NaN
6 7 1.0 1.0 1.0
7 8 1.0 NaN NaN

First filter ony type columns by DataFrame.filter, reshape by DataFrame.stack, so possible call Series.str.get_dummies. Then for 0/1 output use max by first level of MultiIndex and change 1 to NaNs by DataFrame.mask. Last add first column by DataFrame.join:
df1 = df.filter(like='type').stack().str.get_dummies().max(level=0).mask(lambda x: x == 0)
Or use get_dummies and max per columns names and last change 1 to NaNs:
df1 = (pd.get_dummies(df.filter(like='type'), prefix='', prefix_sep='')
.max(level=0, axis=1)
.mask(lambda x: x == 0))
df = df[['id']].join(df1)
print (df)
id cat cow dog
0 1 NaN NaN 1.0
1 2 1.0 NaN NaN
2 3 1.0 NaN 1.0
3 4 NaN 1.0 NaN
4 5 NaN NaN 1.0
5 6 1.0 NaN NaN
6 7 1.0 1.0 1.0
7 8 NaN NaN 1.0

Related

Cutomise the ordering of columns in pivot table after .sort_index(level=1, axis=1)

Dataframe df1
TYPE WEEK A B C D
0 Type1 1 1 1 1 1
1 Type2 2 2 2 2 2
2 Type3 3 3 3 3 3
3 Type4 4 4 4 4 4
Expected output
A C B D A C B D A C B D A C B D
WEEK 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
TYPE
Type1 1.0 1.0 1.0 1.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Type2 NaN NaN NaN NaN 2.0 2.0 2.0 2.0 NaN NaN NaN NaN NaN NaN NaN NaN
Type3 NaN NaN NaN NaN NaN NaN NaN NaN 3.0 3.0 3.0 3.0 NaN NaN NaN NaN
Type4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 4.0 4.0 4.0 4.0
My approach:
df1 = pd.DataFrame(df1)
colname = list(df1.head())
tuples = []
for i in colname:
tuples.append((i,colname.index(i)+1))
index = pd.MultiIndex.from_tuples(tuples, names=["COLUMN", "ORDER"])
df2 = pd.DataFrame(df1.values, columns=index)
df3 = pd.pivot_table(df1,index="TYPE",columns="WEEK", values=['A','B','C','D']).sort_index(level=1, axis=1)
#For df3 cannot attain the expected result because .sort_index(level=1, axis=1) will sort them out alphabetically to ['A','B','C','D']
.sort_index(level=1, axis=1) is required to swap the level of the pivot table.
Another dataframe df2 is generated in order to fix the order of columns as ['A','C','B','D'] to be used in the pivot table
COLUMN TYPE WEEK A B C D
ORDER 1 2 3 4 5 6
0 Type1 1 1 1 1 1
1 Type2 2 2 2 2 2
2 Type3 3 3 3 3 3
3 Type4 4 4 4 4 4
Create a CategoricalDtype before pivoting:
cat = pd.CategoricalDtype(['A', 'C', 'B', 'D'], ordered=True)
df3 = df.melt(['TYPE', 'WEEK'], var_name='COLUMN').astype({'COLUMN': cat}) \
.pivot_table('value', 'TYPE', ['COLUMN', 'WEEK']).sort_index(level=1, axis=1)
Output
>>> df3
COLUMN A C B D A C B D A C B D A C B D
WEEK 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
TYPE
Type1 1.0 1.0 1.0 1.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Type2 NaN NaN NaN NaN 2.0 2.0 2.0 2.0 NaN NaN NaN NaN NaN NaN NaN NaN
Type3 NaN NaN NaN NaN NaN NaN NaN NaN 3.0 3.0 3.0 3.0 NaN NaN NaN NaN
Type4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 4.0 4.0 4.0 4.0

Maintaining dataframe shape when slicing in pandas

I've imported a .csv into pandas and want to extract specific values and put them into a new column whilst maintaining the existing shape.
So df[::3] extracts the data-
1 1
2 4
3 7
4
5
6
7
I want it to look like
1 1
2
3
4 4
5
6
7 7
Here is a solution:
df = pd.read_csv(r"C:/users/k_sego/colsplit.csv",sep=";")
df1 = df[['col1']]
df2 = df[['col2']]
DF = pd.merge(df1,df2, how='outer',left_on=['col1'],right_on=['col2'])
and the result is
col1 col2
0 1.0 1.0
1 2.0 NaN
2 3.0 NaN
3 4.0 4.0
4 5.0 NaN
5 6.0 NaN
6 7.0 7.0
7 NaN NaN
8 NaN NaN
9 NaN NaN
10 NaN NaN

Pandas set all values after first NaN to NaN

For each row I would like to set all values to NaN after the appearance of the first NaN. E.g.:
a b c
1 2 3 4
2 nan 2 nan
3 3 nan 23
Should become this:
a b c
1 2 3 4
2 nan nan nan
3 3 nan nan
So far I only know how to do this with an apply with a for loop over each column per row - it's very slow!
Check with cumprod
df=df.where(df.notna().cumprod(axis=1).eq(1))
a b c
1 2.0 3.0 4.0
2 NaN NaN NaN
3 3.0 NaN NaN

How to remove clustered/unclustered values less than a certain length from pandas dataframe?

If I have a pandas data frame like this:
A
1 1
2 1
3 NaN
4 1
5 NaN
6 1
7 1
8 1
9 1
10 NaN
11 1
12 1
13 1
How do I remove values that are clustered in a length less than some value (in this case four) for example? Such that I get an array like this:
A
1 NaN
2 NaN
3 NaN
4 NaN
5 NaN
6 1
7 1
8 1
9 1
10 NaN
11 NaN
12 NaN
13 NaN
Using groupby and np.where
s = df.groupby(df.A.isnull().cumsum()).transform(lambda s: pd.notnull(s).sum())
df['B'] = np.where(s.A>=4, df.A, np.nan)
Outputs
A B
1 1.0 NaN
2 1.0 NaN
3 NaN NaN
4 1.0 NaN
5 NaN NaN
6 1.0 1.0
7 1.0 1.0
8 1.0 1.0
9 1.0 1.0
10 NaN NaN
11 1.0 NaN
12 1.0 NaN
13 1.0 NaN

How do you shift each row in pandas data frame by a specific value?

If I have a pandas dataframe like this:
2 3 4 NaN NaN NaN
1 NaN NaN NaN NaN NaN
5 6 7 2 3 NaN
4 3 NaN NaN NaN NaN
and an array for the number I would like to shift:
array = [2, 4, 0, 3]
How do I iterate through each row to shift the columns by the number in my array to get something like this:
NaN NaN 2 3 4 NaN
NaN NaN NaN NaN 1 NaN
5 6 7 2 3 NaN
NaN NaN NaN 3 4 NaN
I was trying to do something like this but had no luck.
df = pd.DataFrame(values)
for rows in df.iterrows():
df[rows] = df.shift[change_in_bins[rows]]
Use for loop with loc and shift:
for index,value in enumerate([2, 4, 0, 3]):
df.loc[index,:] = df.loc[index,:].shift(value)
print(df)
0 1 2 3 4 5
0 NaN NaN 2.0 3.0 4.0 NaN
1 NaN NaN NaN NaN 1.0 NaN
2 5.0 6.0 7.0 2.0 3.0 NaN
3 NaN NaN NaN 4.0 3.0 NaN

Categories

Resources