我的熊猫/ numpy生锈了,我写的代码感觉效率低下 .
我正在Python3.x初始化一个numpy零的数组,长度为1000.为了我的目的,这些只是整数:
import numpy as np
array_of_zeros = np.zeros((1000, ), )
我还有以下DataFrame(比我的实际数据小得多)
import pandas as pd
dict1 = {'start' : [100, 200, 300], 'end':[400, 500, 600]}
df = pd.DataFrame(dict1)
print(df)
##
## start end
## 0 100 400
## 1 200 500
## 2 300 600
DataFrame有两列, start
和 end
. 这些值表示一系列值,即 start
将始终是小于 end
的整数 . 在上面,我们看到第一行的范围是 100-400
,接下来是 200-500
,然后是 300-600
.
我的目标是逐行遍历pandas DataFrame,并根据这些索引位置递增numpy数组 array_of_zeros
. 因此,如果 10
到 20
的数据帧中有一行,我想将索引10-20的零增加1 .
这是我想要的代码:
import numpy as np
array_of_zeros = np.zeros((1000, ), )
import pandas as pd
dict1 = {'start' : [100, 200, 300], 'end':[400, 500, 600]}
df = pd.DataFrame(dict1)
print(df)
for idx, row in df.iterrows():
for i in range(int(row.start), int(row.end)+1):
array_of_zeros[i]+=1
它的工作原理!
print(array_of_zeros[15])
## output: 0.0
print(array_of_zeros[600])
## output: 1.0
print(array_of_zeros[400])
## output: 3.0
print(array_of_zeros[100])
## output: 1.0
print(array_of_zeros[200])
## output: 2.0
我的问题:这是非常笨拙的代码!我不应该使用那么多带有numpy数组的for循环!如果输入数据帧非常大,则此解决方案效率非常低
有没有更有效(即更多基于numpy)的方法来避免这种for循环?
for i in range(int(row.start), int(row.end)+1):
array_of_zeros[i]+=1
也许有一个以熊猫为导向的解决方案?
3 回答
您可以使用NumPy数组索引来避免内部循环,即
res[np.arange(A[i][0], A[i][1]+1)] += 1
,但这不是很有效,因为它涉及创建新数组和使用高级索引 .相反,您可以使用
numba
1来优化您的算法,完全符合它的原样 . 以下示例通过将性能关键逻辑移至JIT编译代码,显示了大幅提升性能 .一些基准测试结果:
用于基准测试的代码:
1对于后人,我'm including @piRSquared'对
numba
在这里帮助的原因有很好的评论:numpy.bincount
numpy.add.at
我的解决方案