我的原始数据框如下所示:
A B C
0.10 0.83 0.07
0.40 0.30 0.30
0.70 0.17 0.13
0.72 0.04 0.24
0.15 0.07 0.78
我希望每行变为二值化:1将分配给具有最高值的列,其余的将设置为0,因此之前的数据帧将变为:
A B C
0 1 0
1 0 0
1 0 0
1 0 0
0 0 1
如何做到这一点?
感谢。
答案 0 :(得分:6)
将 numpy
与 argmax
m = np.zeros_like(df.values)
m[np.arange(len(df)), df.values.argmax(1)] = 1
df1 = pd.DataFrame(m, columns = df.columns).astype(int)
# Result
A B C
0 0 1 0
1 1 0 0
2 1 0 0
3 1 0 0
4 0 0 1
<强> 计时 强>
df_test = df.concat([df] * 1000)
def chris_z(df):
m = np.zeros_like(df.values)
m[np.arange(len(df)), df.values.argmax(1)] = 1
return pd.DataFrame(m, columns = df.columns).astype(int)
def haleemur(df):
return df.apply(lambda x: x == x.max(), axis=1).astype(int)
def haleemur_2(df):
return pd.DataFrame((df.T == df.T.max()).T.astype(int), columns=df.columns)
def sacul(df):
return pd.DataFrame(np.where(df.T == df.T.max(), 1, 0),index=df.columns).T
<强> 结果 强>
In [320]: %timeit chris_z(df_test)
358 µs ± 1.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [321]: %timeit haleemur(df_test)
1.14 s ± 45.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [329]: %timeit haleemur_2(df_test)
972 µs ± 11.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [333]: %timeit sacul(df_test)
1.01 ms ± 3.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
答案 1 :(得分:2)
df.apply(lambda x: x == x.max(), axis=1).astype(int)
应该这样做。这可以通过检查值是否是该列的最大值,然后转换为整数(True - > 1,False - > 0)来实现
而不是apply
- 逐行lambda,也可以转置数据帧&amp;与max
比较,然后转置回来
(df.T == df.T.max()).T.astype(int)
最后,一个非常快速的基于numpy的解决方案:
pd.DataFrame((df.T.values == np.amax(df.values, 1)).T*1, columns = df.columns)
输出在所有情况下:
A B C
0 0 1 0
1 1 0 0
2 1 0 0
3 1 0 0
4 0 0 1
答案 2 :(得分:2)
另一个numpy
方法,使用np.where
:
import numpy as np
new_df = pd.DataFrame(np.where(df.T == df.T.max(), 1, 0),index=df.columns).T
A B C
0 0 1 0
1 1 0 0
2 1 0 0
3 1 0 0
4 0 0 1