在多个布尔列

时间:2018-04-13 10:21:05

标签: python pandas dataframe

我有一个拥有10K行电影数据的csv。

在“genre”列中,数据如下所示:

Adventure|Science Fiction|Thriller
Action|Adventure|Science Fiction|Fantasy
Action|Crime|Thriller
Western|Drama|Adventure|Thriller

我想基于流派列创建多个子列(即动作是/否,冒险是/否,戏剧是/否等)。

问题1: 如何首先确定流派列中所有独特的流派标题?

问题2: 在确定所有独特的流派标题后,如何创建所有必需的['插入流派'是/否]列?

2 个答案:

答案 0 :(得分:1)

假设您的列名为Genres,这是一种方式。

res = pd.get_dummies(df['Genres'].str.split('|').apply(pd.Series).stack()).sum(level=0)

#    Action  Adventure  Crime  Drama  Fantasy  ScienceFiction  Thriller  Western
# 0       0          1      0      0        0               1         1        0
# 1       1          1      0      0        1               1         0        0
# 2       1          0      1      0        0               0         1        0
# 3       0          1      0      1        0               0         1        1

然后,您可以通过pd.DataFrame.applymap将二进制值转换为“否”/“是”:

df = df.applymap({0: 'no', 1: 'yes'}.get)

答案 1 :(得分:0)

使用str.get_dummies

df = df['col'].str.get_dummies('|').replace({0:'no', 1:'yes'})

或者:

d = {0:'no', 1:'yes'}
df = df['col'].str.get_dummies('|').applymap(d.get)

为了更好地使用MultiLabelBinarizer

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
df = (pd.DataFrame(mlb.fit_transform(df['col'].str.split('|')) ,
                   columns=mlb.classes_, 
                   index=df.index)
        .applymap(d.get))
print (df)
  Action Adventure Crime Drama Fantasy Science Fiction Thriller Western
0     no       yes    no    no      no             yes      yes      no
1    yes       yes    no    no     yes             yes       no      no
2    yes        no   yes    no      no              no      yes      no
3     no       yes    no   yes      no              no      yes     yes

<强>详细

print (df['col'].str.get_dummies('|'))
   Action  Adventure  Crime  Drama  Fantasy  Science Fiction  Thriller  \
0       0          1      0      0        0                1         1   
1       1          1      0      0        1                1         0   
2       1          0      1      0        0                0         1   
3       0          1      0      1        0                0         1   

   Western  
0        0  
1        0  
2        0  
3        1  

<强>计时

df = pd.concat([df] * 10000, ignore_index=True)


In [361]: %timeit pd.DataFrame(mlb.fit_transform(df['col'].str.split('|')) ,columns=mlb.classes_,  index=df.index)
10 loops, best of 3: 120 ms per loop

In [362]: %timeit df['col'].str.get_dummies('|')
1 loop, best of 3: 324 ms per loop

In [363]: %timeit pd.get_dummies(df['col'].str.split('|').apply(pd.Series).stack()).sum(level=0)
1 loop, best of 3: 7.77 s per loop