我有pandas
数据对象 - data
- 存储为系列丛书。第一个系列在ID1
上编号,第二个在ID2
上编号。
ID1 ID2
1 10259 0.063979
14166 0.120145
14167 0.177417
14244 0.277926
14245 0.436048
15021 0.624367
15260 0.770925
15433 0.918439
15763 1.000000
...
1453 812690 0.752274
813000 0.755041
813209 0.756425
814045 0.778434
814474 0.910647
814475 1.000000
Length: 19726, dtype: float64
我有一个函数,它使用来自此对象的值进行进一步的数据处理。这是功能:
#Function
def getData(ID1, randomDraw):
dataID2 = data[ID1]
value = dataID2.index[np.searchsorted(dataID2, randomDraw, side='left').iloc[0]]
return value
我使用np.vectorize
在DataFrame
- dataFrame
上应用此功能 - 该行有大约2200万行。
dataFrame['ID2'] = np.vectorize(getData)(dataFrame['ID1'], dataFrame['RAND'])
其中ID1
和RAND
是包含正在输入函数的值的列。
代码大约需要6个小时来处理所有内容。 Java
中的类似实现只需要大约6分钟即可获得2200万行数据。
在我的程序上运行分析器时,我发现最昂贵的调用是data
的索引,而第二个最昂贵的调用是searchsorted
。
Function Name: pandas.core.series.Series.__getitem__
Elapsed inclusive time percentage: 54.44
Function Name: numpy.core.fromnumeric.searchsorted
Elapsed inclusive time percentage: 25.49
使用data.loc[ID1]
获取数据会使程序更慢。我怎样才能让它更快?据我所知Python
无法达到与Java相同的效率,但与6分钟相比,6小时似乎没有太大差别。也许我应该使用不同的数据结构/功能?我正在使用Python 2.7
和PTVS
IDE。
添加最低工作示例:
import numpy as np
import pandas as pd
np.random.seed = 0
#Creating a dummy data object - Series within Series
alt = pd.Series(np.array([ 0.25, 0.50, 0.75, 1.00]), index=np.arange(1,5))
data = pd.Series([alt]*1500, index=np.arange(1,1501))
#Creating dataFrame -
nRows = 200000
d = {'ID1': np.random.randint(1500, size=nRows) + 1
,'RAND': np.random.uniform(low=0.0, high=1.0, size=nRows)}
dataFrame = pd.DataFrame(d)
#Function
def getData(ID1, randomDraw):
dataID2 = data[ID1]
value = dataID2.index[np.searchsorted(dataID2, randomDraw, side='left').iloc[0]]
return value
dataFrame['ID2'] = np.vectorize(getData)(dataFrame['ID1'], dataFrame['RAND'])
答案 0 :(得分:1)
使用此代码可以获得更好的性能:
>>> def getData(ts):
... dataID2 = data[ts.name]
... i = np.searchsorted(dataID2.values, ts.values, side='left')
... return dataID2.index[i]
...
>>> dataFrame['ID2'] = dataFrame.groupby('ID1')['RAND'].transform(getData)