Reputation: 1006
So I have a pandas dataframe where certain columns have values of type list and a mix of columns of non-numeric and numeric data.
Example data
dst_address dst_enforcement fwd_count ...
1 1.2.3.4 [Any,core] 8
2 3.4.5.6 [] 9
3 6.7.8.9 [Any] 10
4 8.10.3.2 [core] 0
So far I've been able to find out which columns are non-numeric by these 2 lines of code
col_groups = df.columns.to_series().groupby(df.dtypes).groups
non_numeric_cols = col_groups[np.dtype('O')]
Of all these non-numeric columns, I need to figure out which ones have list as data type and I want to perform one-hot encoding on all non-numeric columns (including those list type)
EDIT: my expected output for above example would be something like
1.2.3.4 | 3.4.5.6 | 6.7.8.9 | 8.10.3.2 | empty | Any | core | fwd_count ...
1 1 0 0 0 0 1 1 8
2 0 1 0 0 1 0 0 9
3 0 0 1 0 0 1 0 10
4 0 0 0 1 0 0 1 0
Upvotes: 0
Views: 1914
Reputation: 25269
I use 3 steps as follows:
df['dst_enforcement'] = df.dst_enforcement.apply(lambda x: x if x else ['empty'])
dm1 = pd.get_dummies(df[df.columns.difference(['dst_enforcement'])], prefix='', prefix_sep='')
dm2 = df.dst_enforcement.str.join('-').str.get_dummies('-')
pd.concat([dm1, dm2], axis=1)
Out[1221]:
fwd_count 1.2.3.4 3.4.5.6 6.7.8.9 8.10.3.2 Any core empty
1 8 1 0 0 0 1 1 0
2 9 0 1 0 0 0 0 1
3 10 0 0 1 0 1 0 0
4 0 0 0 0 1 0 1 0
Upvotes: 2
Reputation: 1642
Give a go to:
non_numeric_cols = col_groups[np.dtype('O')]
for non in non_numeric_cols:
print(pd.get_dummies(df[non].apply(pd.Series)))
Output:
0_1.2.3.4 0_3.4.5.6 0_6.7.8.9 0_8.10.3.2
0 1 0 0 0
1 0 1 0 0
2 0 0 1 0
3 0 0 0 1
0_Any 0_core 1_core
0 1 0 1
1 0 0 0
2 1 0 0
3 0 1 0
When you don't have neither "Any" or "core" the whole row is zeros.
Good luck.
Upvotes: 0
Reputation: 75150
Use unnesting
to unnest the lists to seperate roes and call pd.get_dummies()
:
df_new=unnesting(df,['dst_enforcement']).combine_first(df)
df_new.dst_enforcement=df_new.dst_enforcement.apply(lambda y: 'empty' if len(y)==0 else y)
m=pd.get_dummies(df_new,prefix='',prefix_sep='').groupby('fwd_count').first().reset_index()
print(m)
fwd_count 1.2.3.4 3.4.5.6 6.7.8.9 8.10.3.2 Any core empty
0 0.0 0 0 0 1 0 1 0
1 8.0 1 0 0 0 1 0 0
2 9.0 0 1 0 0 0 0 1
3 10.0 0 0 1 0 1 0 0
Adding the function used for convenience:
def unnesting(df, explode):
idx = df.index.repeat(df[explode[0]].str.len())
df1 = pd.concat([
pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
df1.index = idx
return df1.join(df.drop(explode, 1), how='left')
Upvotes: 1