use*_*828 2 python encoding numpy scikit-learn
传入数据是 0+ 类别的列表:
#input data frame
df = pd.DataFrame({'categories':(list('ABC'), list('BC'), list('A'))})
categories
0 [A, B, C]
1 [B, C]
2 [A]
Run Code Online (Sandbox Code Playgroud)
我想将其转换为一个 DataFrame,每个类别一列,每个单元格中有一个 0/1:
#desired output
A B C
0 1 1 1
1 0 1 1
2 1 0 0
Run Code Online (Sandbox Code Playgroud)
OneHotEncoder 和 LabelEncoder 会陷入困境,因为它们不处理单元格中的列表。当前通过嵌套循环实现了预期的结果for:
#get unique categories ['A','B','C']
categories = np.unique(np.concatenate(x['categories']))
#make empty data frame
binary_df = pd.DataFrame(columns=[c for c in categories],
index=x.index)
print(binary_df)
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
#fill data frame
for i in binary_df.index:
for c in categories:
binary_df.loc[i][c] = 1 if c in np.concatenate(x.loc[i]) else 0
Run Code Online (Sandbox Code Playgroud)
我担心的是,循环表明这是处理大型数据集(数十个类别、数万行或更多行)的极其低效的方法。
有没有办法通过内置的 Numpy/Scikit 函数来实现结果?
pd.get_dummies(pd.DataFrame(df['categories'].tolist()).stack()).sum(level=0)
Out[98]:
A B C
0 1 1 1
1 0 1 1
2 1 0 0
Run Code Online (Sandbox Code Playgroud)
pd.DataFrame(df['categories'].tolist())
Out[100]:
0 1 2
0 A B C
1 B C None
2 A None None
Run Code Online (Sandbox Code Playgroud)
将一系列列表转换为数据帧。
pd.DataFrame(df['categories'].tolist()).stack()
Out[101]:
0 0 A
1 B
2 C
1 0 B
1 C
2 0 A
dtype: object
Run Code Online (Sandbox Code Playgroud)
为以后做好准备get_dummies,同时保留索引。
pd.get_dummies(pd.DataFrame(df['categories'].tolist()).stack())
Out[102]:
A B C
0 0 1 0 0
1 0 1 0
2 0 0 1
1 0 0 1 0
1 0 0 1
2 0 1 0 0
Run Code Online (Sandbox Code Playgroud)
差不多了,但是包含了初始列表中值索引的垃圾信息。
因此,上面的解决方案对这个级别的多索引求和。
编辑:
%timeit结果:
在原始数据框上
df = pd.DataFrame({'categories':(list('ABC'), list('BC'), list('A'))})
Run Code Online (Sandbox Code Playgroud)
有问题提供的解决方案:
100 loops, best of 3: 3.24 ms per loop
这个解决方案:
100 loops, best of 3: 2.29 ms per loop
300行
df = pd.concat(100*[df]).reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)
有问题提供的解决方案:
1 loop, best of 3: 252 ms per loop
这个解决方案:
100 loops, best of 3: 2.45 ms per loop