Search code examples
pythonpandasone-hot-encoding

Pandas - get_dummies with a selected set


With the following DataFrame:

>>> df = pd.DataFrame(data={'category':['a','b','c'],'val':[1,2,3]})
>>> df
  category  val
0        a    1
1        b    2
2        c    3

I'm concatenating the produced dummy columns and droping the original column like so:

>>> df = pd.concat([df, pd.get_dummies(df['category'], prefix='cat')], axis=1).drop(['category'], axis=1)
>>> df
   val  cat_a  cat_b  cat_c
0    1      1      0      0
1    2      0      1      0
2    3      0      0      1

I'm then adding another column for a future unknown value, like so:

>>> df['cat_unkown'] = 0
>>> df
   val  cat_a  cat_b  cat_c  cat_unkown
0    1      1      0      0           0
1    2      0      1      0           0
2    3      0      0      1           0

Now I would like to get_dummies on a new DataFrame, but map it to the available columns, meaning: If a category column exists, use it otherwise set the cat_unkown to 1

for example for the following DataFrame:

  category  val
0        a    1
1        b    2
2        d    3

The result would be:

   val  cat_a  cat_b  cat_c  cat_unkonw
0    1      1      0      0           0
1    2      0      1      0           0
2    3      0      0      0           1

What would be an efficient way to do it?

Update: Just elaborating a bit, In my real-world problem, I have the data frames after the get_dummies produced the results.


Solution

  • I believe you need:

    df = pd.DataFrame(data={'category':['a','b','c'],'val':[1,2,3]})  
    df = pd.concat([df, pd.get_dummies(df['category'], prefix='cat')], axis=1).drop(['category'], axis=1)  
    df['cat_unkown'] = 0
    print (df)
       val  cat_a  cat_b  cat_c  cat_unkown
    0    1      1      0      0           0
    1    2      0      1      0           0
    2    3      0      0      1           0
    
    df1 = pd.DataFrame(data={'category':['a','b','d'],'val':[1,2,3]})    
    df1 = pd.concat([df1, pd.get_dummies(df1['category'], prefix='cat')], axis=1).drop(['category'], axis=1)  
    print (df1)
       val  cat_a  cat_b  cat_d
    0    1      1      0      0
    1    2      0      1      0
    2    3      0      0      1
    

    #get all columns names without val
    orig_cols = df.columns.difference(['val'])
    print (orig_cols)
    Index(['cat_a', 'cat_b', 'cat_c', 'cat_unkown'], dtype='object')
    
     #create dictionary with all columns from df1 which are not in df (also removed vals column)
    dif = dict.fromkeys(df1.columns.difference(['val'] + orig_cols.tolist()), 'cat_unkown')
    print (dif)
    {'cat_d': 'cat_unkown'}
    
    #rename columns and if-else for possible multiplied renamed columns
    df3 = (df1.rename(columns=dif)
            .assign(cat_unkown = lambda x: x.pop('cat_unkown').max(axis=1) 
                                 if isinstance(x['cat_unkown'], pd.DataFrame) 
                                 else x.pop('cat_unkown'))
            .reindex(columns=orig_cols, fill_value=0)
            )
    
    print (df3)
       cat_a  cat_b  cat_c  cat_unkown
    0      1      0      0           0
    1      0      1      0           0
    2      0      0      0           1