【发布时间】:2019-04-28 13:36:44
【问题描述】:
我有两个具有基于位置的值的 HUGE Pandas 数据帧,我需要使用来自 df2 的记录数更新 df1['count'],这些记录数距离 df1 中的每个点都小于 1000m。
这是我导入到 Pandas 中的数据示例
df1 = lat long valA count
0 123.456 986.54 1 0
1 223.456 886.54 2 0
2 323.456 786.54 3 0
3 423.456 686.54 2 0
4 523.456 586.54 1 0
df2 = lat long valB
0 123.456 986.54 1
1 223.456 886.54 2
2 323.456 786.54 3
3 423.456 686.54 2
4 523.456 586.54 1
实际上,df1 有大约 1000 万行,df2 有大约 100 万行
我使用 Pandas DF.itertuples() 方法创建了一个有效的嵌套 FOR 循环,该方法适用于较小的测试数据集(df1=1k Rows & df2=100 Rows 大约需要一个小时才能完成),但完整的数据set 呈指数级增长,根据我的计算需要数年才能完成。这是我的工作代码...
import pandas as pd
import geopy.distance as gpd
file1 = 'C:\\path\\file1.csv'
file2 = 'C:\\path\\file2.csv'
df1 = pd.read_csv(file1)
df2 = pd.read_csv(file2)
df1.sort_values(['long', 'lat']), inplace=True)
df2.sort_values(['long', 'lat']), inplace=True)
for irow in df1.itertuples():
count = 0
indexLst = []
Location1 = (irow[1], irow[2])
for jrow in df2.itertuples():
Location2 = (jrow[1], jrow[2])
if gpd.distance(Location1, Location2).kilometers < 1:
count += 1
indexLst.append(jrow[0])
if count > 0: #only update DF if a match is found
df1.at[irow[0],'count'] = (count)
df2.drop(indexLst, inplace=True) #drop rows already counted from df2 to speed up next iteration
#save updated df1 to new csv file
outFileName = 'combined.csv'
df1.to_csv(outFileName, sep=',', index=False)
df2 中的每个点只需要计算一次,因为 df1 中的点是均匀分布的。为此,我添加了一个 drop 语句,以便在计算完行后从 df2 中删除行,以期缩短迭代时间。我最初也尝试创建一个合并/连接语句,而不是嵌套循环,但没有成功。
现阶段,非常感谢您对提高效率的任何帮助!
编辑: 目标是用 df2 中
df1 = lat long valA count
0 123.456 986.54 1 3
1 223.456 886.54 2 1
2 323.456 786.54 3 9
3 423.456 686.54 2 2
4 523.456 586.54 1 5
【问题讨论】:
-
欢迎@dP8884,为了澄清问题,我理解这段代码的意图是从
df1获取一对纬度/经度,然后添加到纬度数的计数器/df2中距离不到 1 公里的 /long 点?所以最后你会得到df1中的纬度/经度,并更新到count列,它在df2中找到的点数小于1 公里? -
是的,没错。我将更新我的问题以反映预期的输出应该是什么样子。谢谢。
-
应该有一种方法可以根据您知道超出范围的 lat/long 组合进行某种过滤(即,lat 或 long 相距超过一个度数),但我不知道不知道在你的情况下最好的方法。
标签: python pandas performance loops dataframe