Python 加速将概率转换为二进制特征

Python 加速将概率转换为二进制特征,python,pandas,performance,numpy,vectorization,Python,Pandas,Performance,Numpy,Vectorization,我有一个有3列的数据框,在每一行中,我有可能这一行,特征T的值是1,2和3 import pandas as pd import numpy as np np.random.seed(42) df = pd.DataFrame({"T1" : [0.8,0.5,0.01],"T2":[0.1,0.2,0.89],"T3":[0.1,0.3,0.1]}) 对于第0行,T为1,概率为80%,2为10%,3为10% 我想模拟每行的T值,并将列T1、T2、T3更改为二进制特征。 我有一个解决方案,但它

我有一个有3列的数据框,在每一行中,我有可能这一行,特征T的值是1,2和3

import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({"T1" : [0.8,0.5,0.01],"T2":[0.1,0.2,0.89],"T3":[0.1,0.3,0.1]})
对于第0行,T为1,概率为80%,2为10%,3为10%

我想模拟每行的T值,并将列T1、T2、T3更改为二进制特征。 我有一个解决方案,但它需要在数据帧的行上循环,速度非常慢(我的真实数据帧有100多万行):

有没有办法把这段代码矢量化

谢谢大家!

这是一个基于-

1000000行上的计时-

我们可以为此使用
numpy

result = pd.get_dummies((np.random.rand(len(df), 1) > df.cumsum(axis=1)).idxmin(axis=1))
这将生成一列随机值,并将其与数据帧的按列求和进行比较,从而生成值的
dataframe
,其中第一个
False
值显示随机值属于哪个“bucket”。使用
idxmax
,我们可以得到这个bucket的索引,然后我们可以使用
pd.get\u dummies
将其转换回来

例如:

import numpy as np
import pandas as pd

np.random.seed(0)
data = np.random.rand(10, 3)
normalised = data / data.sum(axis=1)[:, np.newaxis]

df = pd.DataFrame(normalised)
result = pd.get_dummies((np.random.rand(len(df), 1) > df.cumsum(axis=1)).idxmin(axis=1))

print(result)
输出:

   0  1  2
0  1  0  0
1  0  0  1
2  0  1  0
3  0  1  0
4  1  0  0
5  0  0  1
6  0  1  0
7  0  1  0
8  0  0  1
9  0  1  0
注:

大部分减速来自于pd.get_傻瓜;如果使用Divakar的方法
pd.DataFrame(result.view('i1'),index=df.index,columns=df.columns)
,速度会快得多

# Setup input
In [169]: N = 1000000
     ...: a = np.random.rand(N,3)
     ...: df = pd.DataFrame(a/a.sum(1,keepdims=1),columns=[['T1','T2','T3']])

# @gmds's soln
In [171]: %timeit pd.get_dummies((np.random.rand(len(df), 1) > df.cumsum(axis=1)).idxmin(axis=1))
1 loop, best of 3: 4.82 s per loop

# Soln from this post
In [172]: %%timeit 
     ...: ar_out = matrixprob_to_onehot(df.values)
     ...: df_out = pd.DataFrame(ar_out.view('i1'), index=df.index, columns=df.columns)
10 loops, best of 3: 43.1 ms per loop
result = pd.get_dummies((np.random.rand(len(df), 1) > df.cumsum(axis=1)).idxmin(axis=1))
import numpy as np
import pandas as pd

np.random.seed(0)
data = np.random.rand(10, 3)
normalised = data / data.sum(axis=1)[:, np.newaxis]

df = pd.DataFrame(normalised)
result = pd.get_dummies((np.random.rand(len(df), 1) > df.cumsum(axis=1)).idxmin(axis=1))

print(result)
   0  1  2
0  1  0  0
1  0  0  1
2  0  1  0
3  0  1  0
4  1  0  0
5  0  0  1
6  0  1  0
7  0  1  0
8  0  0  1
9  0  1  0