我不太擅长使用 pandas/numpy,我写的代码感觉效率低下。
我正在 Python 3.x 中初始化一个长度为 1000 的 numpy 数组,并将其全部赋值为零。对于我的需求来说,这些只是整数:
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
的行,我想将0增加+1,以便索引为10-20。
以下是实现我所需功能的代码:
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
也许有一个以pandas为导向的解决方案?
njit
是jit(nopython=True)
。 - piRSquarednjit
,但我认为对于那些刚接触numba
的人来说,有时更明确一些。 - jppnumba
来优化@piRSquared的代码? - ShanZhengYangnumba
的优势在于循环非常高效。虽然它可以理解大部分Numpy的api,但通常最好避免在循环中创建Numpy对象。我的代码为数据框中的每一行创建了一个Numpy数组,然后在使用bincount之前将它们连接起来。@jpp的numba
代码几乎不会创建额外的对象,并且利用了已有的许多内容。我使用Numpy的解决方案和jpp的numba
解决方案之间的差异约为4-5倍。两者都是线性的,应该非常快。 - piRSquared