为特征工程目的实现以下逻辑。一个简单的方法很容易,但想知道是否有更有效的解决方案,任何人都可以想到。如果您不想实现整个代码,我们将不胜感激!
获取此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
中可以有任意数量的字符串和类别,所以我想知道是否有办法这样做。
答案 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类并实现惰性列评估,如果派生列不存在,请实现逻辑并将其添加到基类列集合。