Pandas 为列表字典中的每个字符串创建虚拟特征
Pandas create dummy features for each string in a dictionary of lists
为特征工程目的实施以下逻辑。一个简单的方法很容易,但想知道是否有任何人都能想到的更有效的解决方案。如果您不想实现整个代码,我们将不胜感激!
取这个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']}
我们想为字典中的每个字符串和每个类别创建一个 column/feature。 1 如果字符串包含在 description
列中 0 否则。
所以这个玩具示例的输出如下所示:
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
中可以有任意数量的字符串和类别,所以我想知道是否有其他方法可以做到这一点。
您可以扩展 pandas DataFrame class 并实施惰性列评估,如果派生列不存在,则实施逻辑并将其添加到基础 class 列collection.
有趣的问题。在下面编写您想要的代码,但可能有更短的方法:
#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)
这是一个向量化的方法。主要观察是 random_animals.description.str.contains
应用于字符串时 returns 一系列指标,每行一个指标 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
为特征工程目的实施以下逻辑。一个简单的方法很容易,但想知道是否有任何人都能想到的更有效的解决方案。如果您不想实现整个代码,我们将不胜感激!
取这个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']}
我们想为字典中的每个字符串和每个类别创建一个 column/feature。 1 如果字符串包含在 description
列中 0 否则。
所以这个玩具示例的输出如下所示:
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
中可以有任意数量的字符串和类别,所以我想知道是否有其他方法可以做到这一点。
您可以扩展 pandas DataFrame class 并实施惰性列评估,如果派生列不存在,则实施逻辑并将其添加到基础 class 列collection.
有趣的问题。在下面编写您想要的代码,但可能有更短的方法:
#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)
这是一个向量化的方法。主要观察是 random_animals.description.str.contains
应用于字符串时 returns 一系列指标,每行一个指标 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