简而言之,我正在尝试比较第一列的2列DataFrame
与另一个列中的相同列的值DataFrame
。匹配的行的索引在first中存储为新列DataFrame
。
让我解释一下:我正在使用地理特征(纬度/经度),并且主要对象DataFrame
(称为df
)具有约55M观测值,看起来有点像这样:
如您所见,只有两行数据看起来合法(索引2和4)。
第二个DataFrame
(称为)legit_df
要小得多,并且拥有我认为合法的所有地理数据:
无需研究WHY,主要任务涉及将每次经纬度观测值与df
的数据进行比较legit_df
。匹配成功后,会将的索引legit_df
复制到的新列中df
,结果df
如下所示:
该值-1
用于显示没有成功匹配的时间。在上面的示例中,唯一有效的观测值是索引2和4的观测值,它们在中的索引1和2处找到了匹配项legit_df
。
我当前解决此问题的方法使用.apply()
。是的,它很慢,但是我找不到一种方法来对下面的函数进行矢量化或使用Cython对其进行加速:
def getLegitLocationIndex(lat, long):
idx = legit_df.index[(legit_df['pickup_latitude'] == lat) & (legit_df['pickup_longitude'] == long)].tolist()
if (not idx):
return -1
return idx[0]
df['legit'] = df.apply(lambda row: getLegitLocationIndex(row['pickup_latitude'], row['pickup_longitude']), axis=1)
由于此代码在DataFrame
具有55M观测值的情况下非常慢,因此我的问题是:有没有更快的方法来解决此问题?
我正在分享一个简短,自包含,正确(可编译)的示例,以帮助您提出更快速的选择:
import pandas as pd
import numpy as np
data1 = { 'pickup_latitude' : [41.366138, 40.190564, 40.769413],
'pickup_longitude' : [-73.137393, -74.689831, -73.863300]
}
legit_df = pd.DataFrame(data1)
display(legit_df)
####################################################################################
observations = 10000
lat_numbers = [41.366138, 40.190564, 40.769413, 10, 20, 30, 50, 60, 80, 90, 100]
lon_numbers = [-73.137393, -74.689831, -73.863300, 11, 21, 31, 51, 61, 81, 91, 101]
# Generate 10000 random integers between 0 and 10
random_idx = np.random.randint(low=0, high=len(lat_numbers)-1, size=observations)
lat_data = []
lon_data = []
# Create a Dataframe to store 10000 pairs of geographical coordinates
for i in range(observations):
lat_data.append(lat_numbers[random_idx[i]])
lon_data.append(lon_numbers[random_idx[i]])
df = pd.DataFrame({ 'pickup_latitude' : lat_data, 'pickup_longitude': lon_data })
display(df.head())
####################################################################################
def getLegitLocationIndex(lat, long):
idx = legit_df.index[(legit_df['pickup_latitude'] == lat) & (legit_df['pickup_longitude'] == long)].tolist()
if (not idx):
return -1
return idx[0]
df['legit'] = df.apply(lambda row: getLegitLocationIndex(row['pickup_latitude'], row['pickup_longitude']), axis=1)
display(df.head())
上面的示例df
仅用10k进行创建,observations
在我的机器上运行大约需要7秒。如果使用100k observations
,则需要约67秒才能运行。现在想象一下当我必须处理5500万行时的痛苦...
我认为您可以使用合并而不是当前逻辑来显着加快此速度:
full_df = df.merge(legit_df.reset_index(), how="left", on=["pickup_longitude", "pickup_latitude"])
这将重置参考表的索引以使其成为列并按经度连接
full_df = full_df.rename(index = str, columns={"index":"legit"})
full_df["legit"] = full_df["legit"].fillna(-1).astype(int)
这将重命名为您想要的列名称,并使用-1填充连接列中的所有缺失项
基准测试:
旧方法: 5.18 s ± 171 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
新的方法: 23.2 ms ± 1.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句