如何选择满足条件的最近邻?

2024-10-01 15:34:06 发布

您现在位置:Python中文网/ 问答频道 /正文

问题:如何为geodataframe中的所有元素选择“n个满足条件的最近邻”?你知道吗

示例:“对于森林中的所有树木,半径100米范围内最高的两棵松树的高度是多少?”(注意“tree”不一定是“pine”。)

如果我只想每棵树都有最近的树,我可以用

libpysal.weights.KNN.from_dataframe(df_g, k=2, radius=100)

(给定一个geodataframe)

我正在寻找一种方法来获得满足条件的最近邻居。你知道吗

工作示例

这段代码定义了一个带有9个点的geodataframe:

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型邻居。你知道吗

所以,对于中心点,我想在橙色点而不是蓝色点之间寻找邻居:

Points with types

如果类型不是问题,我可以循环查看最近的邻居,如:

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'

对于中心点,将选择两个绿点,如图所示:

Selection without type

不过,我只想考虑橙色点。你知道吗

简单的“修复”:

当然,我可以选择“足够”的邻居,然后过滤它们:

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'

Simple fix

如图所示,它选择了正确的点。然而,有两个问题:

  • 没有明确的方法来选择“足够”的邻居。中间有足够的蓝点。我不会抓住橙色的点。你知道吗
  • 当谈论数百万个密度变化很大的点时,这个比例很差。选择100个邻居来查找4个邻居将在处理时间方面受到惩罚。你知道吗

这似乎是一个有人会在某个时候解决的问题。有什么建议吗?我应该考虑学习吗?你知道吗


Tags: fromdfgetindexvalueneighborsmeanpoints
1条回答
网友
1楼 · 发布于 2024-10-01 15:34:06

如注释中所述,您可以使用DistanceBand而不是KNN进行第一次筛选(在KNN中,您实际上不知道必须选择多少个才能至少有2个PINE)。你知道吗

从上面的gdf开始:

W = libpysal.weights.DistanceBand.from_dataframe(gdf, threshold=2)

results = []  # it is faster to save to list than directly to gdf
for index, row in gdf.iterrows():
    neighbors = W.neighbors[index]
    subset = gdf.loc[neighbors]  # get all within threshold
    limited = subset.loc[subset.types == 1]  # limit to type you want - here you can do more filtering
    if len(limited) > 0:  # if something of type 1 is close enough
        limited['dist'] = limited.geometry.distance(row.geometry)  #get distances
        limited.nsmallest(n=2, columns='dist')
        results.append(list(limited.index))  # save indices of selection
    else:
        results.append(None)

gdf['result'] = results  # save to gdf

这将保存满足条件(或无)的点的索引。你知道吗

不过,我不确定它在大数据集上的表现,但熊猫过滤应该不是问题,而且距离有限的df是矢量化的。你知道吗

相关问题 更多 >

    热门问题