我有一个如下数据框:
In[8]: df = pd.DataFrame({'transport': ['Car;Bike;Horse','Car','Car;Bike', 'Horse;Car']})
df
Out[8]:
transport
0 Car;Bike;Horse
1 Car
2 Car;Bike
3 Horse;Car
我想把它转换成这样的东西:
In[9]: df2 = pd.DataFrame({'transport_car': [True,True,True,True],'transport_bike': [True,False,True,False], 'transport_horse': [True,False,False,True]} )
df2
Out[10]:
transport_bike transport_car transport_horse
0 True True True
1 False True False
2 True True False
3 False True True
我得到了一个解决方案,但感觉非常'黑客'和'unpythonic'。 (它适用于我相当小的数据集)
In[11]:
# get set of all possible values
new_columns = set()
for element in set(df.transport.unique()):
for transkey in str(element).split(';'):
new_columns.add(transkey)
print(new_columns)
# Use broadcast to initialize all columns with default value.
for col in new_columns:
df['trans_'+str(col).lower()] = False
# Change cells appropiate to keywords
for index, row in df.iterrows():
for key in new_columns:
if key in row.transport:
df.set_value(index, 'trans_'+str(key).lower(), True)
df
Out[11]:
transport trans_bike trans_car trans_horse
0 Car;Bike;Horse True True True
1 Car False True False
2 Car;Bike True True False
3 Horse;Car False True True
我的目标是使用第二个表示来执行一些评估,以回答诸如“汽车使用频率多少?”,“汽车与马一起使用的频率”等问题。
This和this回答建议使用pivot
和eval
可能是要走的路,但我不确定。
那么将DataFrame从第一个表示转换为第二个表示最好的方法是什么?
答案 0 :(得分:3)
您可以使用apply
为每个条目构建一个系列,并将拆分的字段作为索引。这将导致数据框的索引为列:
df.transport.apply(lambda x: pd.Series(True, x.split(";"))).fillna(False)
答案 1 :(得分:2)
我决定用一个工作示例扩展the great @Metropolis's answer:
In [249]: %paste
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df=1)
X = vectorizer.fit_transform(df.transport.str.replace(';',' '))
r = pd.DataFrame(X.toarray(), columns=vectorizer.get_feature_names())
## -- End pasted text --
In [250]: r
Out[250]:
bike car horse
0 1 1 1
1 0 1 0
2 1 1 0
3 0 1 1
现在您可以将其加入源DF:
In [251]: df.join(r)
Out[251]:
transport bike car horse
0 Car;Bike;Horse 1 1 1
1 Car 0 1 0
2 Car;Bike 1 1 0
3 Horse;Car 0 1 1
时间:适用于40K行DF:
In [254]: df = pd.concat([df] * 10**4, ignore_index=True)
In [255]: df.shape
Out[255]: (40000, 1)
In [256]: %timeit df.transport.apply(lambda x: pd.Series(True, x.split(";"))).fillna(False)
1 loop, best of 3: 33.8 s per loop
In [257]: %%timeit
...: vectorizer = CountVectorizer(min_df=1)
...: X = vectorizer.fit_transform(df.transport.str.replace(';',' '))
...: r = pd.DataFrame(X.toarray(), columns=vectorizer.get_feature_names())
...:
1 loop, best of 3: 732 ms per loop
答案 2 :(得分:1)
我会考虑使用Scikit-learn提供的Count Vectorizer。向量化器将构造一个向量,其中每个索引引用一个术语,该值指的是该术语在记录中的出现次数。
在其他答案中提出的优于家庭滚动方法的优点是大数据集的效率和普遍性。显然,缺点是带来额外的依赖性。