Pandas为列表字典中的每个字符串创建虚拟特征

时间:2018-05-24 20:01:55

标签: python pandas dummy-variable

为特征工程目的实现以下逻辑。一个简单的方法很容易,但想知道是否有更有效的解决方案,任何人都可以想到。如果您不想实现整个代码,我们将不胜感激!

获取此DataFrame和字典

import pandas as pd
random_animals = pd.DataFrame(
                {'description':['xdogx','xcatx','xhamsterx','xdogx'
                                ,'xhorsex','xdonkeyx','xcatx']
                })


cat_dict = {'category_a':['dog','cat']
            ,'category_b':['horse','donkey']}

我们想为字典中的每个字符串创建一个列/功能,并为每个类别创建一个列/功能。如果字符串包含在description列中,则为1,否则为

所以这个玩具示例的输出看起来像是:

  description  is_dog is_cat is_horse is_donkey is_category_a is_category_b
0       xdogx       1      0        0         0             1             0
1       xcatx       0      1        0         0             1             0    
2   xhamsterx       0      0        0         0             0             0
3       xdogx       1      0        0         0             1             0
4     xhorsex       0      0        1         0             0             1
5    xdonkeyx       0      0        0         1             0             1
6       xcatx       0      1        0         0             1             0

对于每个需要和运行的输出列,简单的方法将迭代一次(对于每个列,为简单起见,这里只是硬编码的is_dog)

random_animals['is_dog'] = random_animals['description'].str.contains('dog')*1

cat_dict中可以有任意数量的字符串和类别,所以我想知道是否有办法这样做。

3 个答案:

答案 0 :(得分:2)

有趣的问题。我在下面编写了你想要的内容,但有一个简短的方法可以做到这一点:

#Creating the DataFrame with columns of zeros

names = [x[1:-1] for x in random_animals.description.unique()]
categories = list(cat_dict.keys())
columns = names + categories
df_names = pd.DataFrame(0, index=np.arange(len(random_animals)), 
columns=columns)
df = pd.concat([random_animals, df_names], axis = 1)

#Populating the Dataframe - Automating your solution

#For animal names
for i in range(len(df.columns)-1):
    df[df.columns[i+1]] = df['description'].str.contains(df.columns[i+1])*1

#For categories
if df.columns[i+1] in list(cat_dict.keys()):
    searchfor = cat_dict[df.columns[i+1]]
    df[df.columns[i+1]]= df['description'].str.contains('|'.join(searchfor))*1

#Finally renaming names pattern of columns from "dog" to "is_dog"...:

for column in df.columns:
 if column in names:
     column_new = "is_"+column
     df[column_new] = df[column]
     df = df.drop(column, axis =1)

答案 1 :(得分:2)

这是一个矢量化方法。主要观察结果是,random_animals.description.str.contains应用于字符串时会返回一系列指标,每行random_animals一个。

由于random_animals.description.str.contains本身就是一个矢量化函数,我们可以将它应用于动物集合以获得完整的指标矩阵。

最后,我们可以通过在不同列之间强制执行逻辑来添加类别。这可能比多次检查字符串包含更快。

import pandas as pd
random_animals = pd.DataFrame(
                {'description':['xdogx','xcatx','xhamsterx','xdogx'
                                ,'xhorsex','xdonkeyx','xcatx']
                })


cat_dict = {'category_a':['dog', 'cat']
            ,'category_b':['horse', 'donkey']}

# create a Series containing all individual animals (without duplicates)
animals = pd.Series([animal for v in cat_dict.values()
        for animal in v])

df = pd.DataFrame(
        animals.apply(random_animals.description.str.contains).T.values,
        index  = random_animals.description,
        columns = animals).astype(int)

for cat, animals in cat_dict.items():
    df[cat] = df[animals].any(axis=1).astype(int)

             # dog  cat  horse  donkey  category_a  category_b
# description
# xdogx          1    0      0       0           1           0
# xcatx          0    1      0       0           1           0
# xhamsterx      0    0      0       0           0           0
# xdogx          1    0      0       0           1           0
# xhorsex        0    0      1       0           0           1
# xdonkeyx       0    0      0       1           0           1
# xcatx          0    1      0       0           1           0

答案 2 :(得分:0)

您可以扩展pandas DataFrame类并实现惰性列评估,如果派生列不存在,请实现逻辑并将其添加到基类列集合。