【发布时间】:2019-09-11 18:26:00
【问题描述】:
问题:如何为地理数据框中的所有元素选择“满足条件的 n 个最近邻”?
示例: “对于森林中的所有树木,半径 100 m 内两棵最高的松树的高度是多少?”(注意“树”不一定是“松树”。)
如果我只想要每棵树最近的相邻树,我可以使用
libpysal.weights.KNN.from_dataframe(df_g, k=2, radius=100)
(给定一个地理数据框)
我正在寻找一种方法来获取满足条件的最近邻居。
工作示例
这段代码定义了一个包含 9 个点的地理数据框:
import pandas as pd, libpysal, geopandas as gp,matplotlib.pyplot as plt
from shapely.wkt import loads
# 18 points with values and types
points=['POINT (0.1 0.2)','POINT (-1 0)','POINT (1 0)','POINT (0 -1)','POINT (0 1)','POINT (-2 0)','POINT (2 0)','POINT (0 -2)','POINT (0 2)']
values=[9,8,7,6,5,4,3,2,1]
types=[0,0,0,0,0,1,1,1,1]
df=pd.DataFrame({'points':points,'value':values,'types':types})
gdf=gp.GeoDataFrame(df,geometry=[loads(x) for x in df.points])
我想在半径为 2 的范围内寻找类型为 1 的邻居。
所以,对于中心点,我想在橙色点而不是蓝色点之间寻找邻居:
如果类型不是问题,我可以遍历最近的邻居,例如:
knn2 = libpysal.weights.KNN.from_dataframe(gdf, k=2,radius=2)
for index,row in gdf.iterrows(): # Looping over all points
knn_neighbors = knn2.neighbors[index] # Get neighbors
knnsubset = gdf.iloc[knn_neighbors] # Get subdataframe
print("Mean: ",knnsubset['value'].mean()) # Calculating mean of 'value'
对于中心点,将选择两个绿色点,如图所示:
但是,我只想考虑橙色点。
简单的“修复”:
我当然可以选择“足够”的邻居,然后过滤它们:
knn2 = libpysal.weights.KNN.from_dataframe(gdf, k=8,radius=2) # Select enough neighbors
for index,row in gdf.iterrows(): # Looping over all points
knn_neighbors = knn2.neighbors[index] # Get neighbors
knnsubset = gdf.iloc[knn_neighbors] # Get subdataframe
knnsubset=knnsubset[knnsubset.types==1].head(2) #Require type 1 and take the two first
print("Mean: ",knnsubset['value'].mean()) # Calculating mean of 'value'
如图所示,它选择了正确的点。但是,有两个问题:
- 没有选择“足够”邻居的明确方法。中间是否有足够的蓝点。我不会抓住橙色点。
- 当谈论数百万个密度变化很大的点时,这很难扩展。选择 100 个邻居来找到 4 个会导致处理时间方面的损失。
这似乎是一个有人会在某个时候解决的问题。任何指针?我应该考虑 sklearn 吗?
【问题讨论】:
-
对于给定的点,你能不能只按标准过滤,然后使用旧的 sqrt(x^2+y^2) 公式计算该点与其他点之间的距离,然后按距离排序并取前 N 行?
-
我想不出一种相比之下不会表现得非常糟糕的方法。
-
不要使用 KNN,而是使用 DistanceBand 在最大距离内获取所有数据,然后过滤结果数据框以获得您想要的数据。过滤掉松树,然后检查哪两个最接近。
-
@martinfleis,这很有趣。我可以大胆地问如何在“简单修复”下更改上面的sn-p吗?我似乎找不到有关如何使用 DistanceBand 对象过滤数据框的示例。
标签: python pandas spatial geopandas