Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 仅当点位于附近时,才从点列表创建多边形_Python_Pandas_Geopandas_Shapely - Fatal编程技术网

Python 仅当点位于附近时,才从点列表创建多边形

Python 仅当点位于附近时,才从点列表创建多边形,python,pandas,geopandas,shapely,Python,Pandas,Geopandas,Shapely,我有一个点列表(经度和纬度),以及它们在地理数据框中的关联点几何图形。所有的点都应该能够细分为单独的多边形,因为这些点通常聚集在几个区域中。我想做的是使用某种算法在点上循环并检查上一个点和当前点之间的距离。如果距离足够小,它会将这些点组合在一起。这个过程将一直持续到当前点太远为止。它将从这些闭合点生成多边形,然后继续处理下一组点 gdf longitude latitude geometry 0 -76.575249 21.157229 POINT (-76.57525 21

我有一个点列表(经度和纬度),以及它们在地理数据框中的关联点几何图形。所有的点都应该能够细分为单独的多边形,因为这些点通常聚集在几个区域中。我想做的是使用某种算法在点上循环并检查上一个点和当前点之间的距离。如果距离足够小,它会将这些点组合在一起。这个过程将一直持续到当前点太远为止。它将从这些闭合点生成多边形,然后继续处理下一组点

gdf
longitude   latitude    geometry
0   -76.575249  21.157229   POINT (-76.57525 21.15723)
1   -76.575035  21.157453   POINT (-76.57503 21.15745)
2   -76.575255  21.157678   POINT (-76.57526 21.15768)
3   -76.575470  21.157454   POINT (-76.57547 21.15745)
5   -112.973177 31.317333   POINT (-112.97318 31.31733)
... ... ... ...
2222    -113.492501 47.645914   POINT (-113.49250 47.64591)
2223    -113.492996 47.643609   POINT (-113.49300 47.64361)
2225    -113.492379 47.643557   POINT (-113.49238 47.64356)
2227    -113.487443 47.643142   POINT (-113.48744 47.64314)
2230    -105.022627 48.585669   POINT (-105.02263 48.58567)
因此,在上面的数据中,前4个点将分组在一起并变成一个多边形。然后,它将移动到下一组,以此类推。每组点的间距不均匀,即下一组可能是7对点,以下可能是3对点。理想情况下,最终输出将是另一个geodataframe,它只是一组多边形。

看起来像是一个工作

您可能需要注意如何定义您的距离(通过地球的实际距离,或周围的最短路径?)


将每个簇转化为多边形取决于要执行的操作。。。您可以尝试使用DBSCAN群集,因为它会自动找到最佳群集数量,并且您可以指定点之间的最大距离(ε)

使用您的示例,该算法识别两个集群

import pandas as pd
from sklearn.cluster import DBSCAN

df = pd.DataFrame(
    [
        [-76.575249, 21.157229, (-76., 21.15723)],
        [-76.575035, 21.157453, (-76.57503, 21.15745)],
        [-76.575255, 21.157678, (-76.57526, 21.15768)],
        [-76.575470, 21.157454, (-76.57547, 21.15745)],
        [-112.973177, 31.317333, (-112.97318, 31.31733)],
        [-113.492501, 47.645914, (-113.49250, 47.64591)],
        [-113.492996, 47.643609, (-113.49300, 47.64361)],
        [-113.492379, 47.643557, (-113.49238, 47.64356)],
        [-113.487443, 47.643142, (-113.48744, 47.64314)],
        [-105.022627, 48.585669, (-105.02263, 48.58567)]
    ], columns=["longitude", "latitude", "geometry"])

clustering = DBSCAN(eps=0.3, min_samples=4).fit(df[['longitude','latitude']].values)
gdf = pd.concat([df, pd.Series(clustering.labels_, name='label')], axis=1)
print(gdf)
gdf.plot.scatter(x='longitude', y='latitude', c='label')

    longitude   latitude                geometry  label
0  -76.575249  21.157229       (-76.0, 21.15723)      0
1  -76.575035  21.157453   (-76.57503, 21.15745)      0
2  -76.575255  21.157678   (-76.57526, 21.15768)      0
3  -76.575470  21.157454   (-76.57547, 21.15745)      0
4 -112.973177  31.317333  (-112.97318, 31.31733)     -1 # not in cluster
5 -113.492501  47.645914   (-113.4925, 47.64591)      1
6 -113.492996  47.643609    (-113.493, 47.64361)      1
7 -113.492379  47.643557  (-113.49238, 47.64356)      1
8 -113.487443  47.643142  (-113.48744, 47.64314)      1
9 -105.022627  48.585669  (-105.02263, 48.58567)     -1 # not in cluster
如果我们向您的数据集中添加随机数据,运行聚类算法,过滤掉那些不在聚类中的数据点,您就会更清楚地了解它是如何工作的

import numpy as np
rng = np.random.default_rng(seed=42)
arr2 = pd.DataFrame(rng.random((3000, 2)) * 100, columns=['latitude', 'longitude'])
randdf = pd.concat([df[['latitude', 'longitude']], arr2]).reset_index()
clustering = DBSCAN(eps=1, min_samples=4).fit(randdf[['longitude','latitude']].values)
labels =  pd.Series(clustering.labels_, name='label')
gdf = pd.concat([randdf[['latitude', 'longitude']], labels], axis=1)

subgdf = gdf[gdf['label']> -1]
subgdf.plot.scatter(x='longitude', y='latitude', c='label', colormap='viridis', figsize=(20,10))

print(gdf['label'].value_counts())
-1     2527
 16      10
 3        8
 10       8
 50       8
       ... 
 57       4
 64       4
 61       4
 17       4
 0        4
Name: label, Length: 99, dtype: int64

从这个数据帧中获取聚集点相对简单。大概是这样的:

subgdf['point'] = subgdf.apply(lambda x: (x['latitude'], x['longitude']), axis=1)
subgdf.groupby(['label'])['point'].apply(list)

label
0     [(21.157229, -76.575249), (21.157453, -76.5750...
1     [(47.645914, -113.492501), (47.643609, -113.49...
2     [(46.67210037270342, 4.380376578722878), (46.5...
3     [(85.34030732681661, 23.393948586534073), (86....
4     [(81.40203846660347, 16.697291990770392), (82....
                            ...                        
93    [(61.419880354359925, 23.25522624430636), (61....
94    [(50.893415175135424, 90.70863269095085), (52....
95    [(88.80586950148697, 81.17523712192651), (88.6...
96    [(34.23624333000541, 40.8156668231013), (35.86...
97    [(16.10456828199399, 67.41443008931344), (15.9...
Name: point, Length: 98, dtype: object
虽然您可能需要进行某种排序,以确保在绘制多边形时连接了最近的点

您可以使用哈弗公式对距离内的点进行分组。使用公式为每个点(下面的函数)创建多边形,然后从点的主列表中过滤内部的点并重复,直到没有更多的点为止

#import modules
import numpy as np
import pandas as pd
import geopandas as gpd
from geopandas import GeoDataFrame, GeoSeries
from shapely import geometry
from shapely.geometry import Polygon, Point
from functools import partial
import pyproj
from shapely.ops import transform

#function to create polygons on radius
def polycir(lat, lon, radius):
    
    local_azimuthal_projection = """+proj=aeqd +R=6371000 +units=m +lat_0={} +lon_0= 
                                  {}""".format(lat, lon)
    
    wgs84_to_aeqd = partial(
        pyproj.transform,
        pyproj.Proj("+proj=longlat +datum=WGS84 +no_defs"),
        pyproj.Proj(local_azimuthal_projection),
    )
    
    aeqd_to_wgs84 = partial(
        pyproj.transform,
        pyproj.Proj(local_azimuthal_projection),
        pyproj.Proj("+proj=longlat +datum=WGS84 +no_defs"),
    )

    center = Point(float(lon), float(lat))
    point_transformed = transform(wgs84_to_aeqd, center)
    buffer = point_transformed.buffer(radius)
    # Get the polygon with lat lon coordinates
    circle_poly = transform(aeqd_to_wgs84, buffer)
    
    return circle_poly

#Convert df to gdf
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.longitude, df.latitude))

#Create circle polygons col
gdf['polycir'] = [polycir(x, y, <'Radius in Meters'>) for x, y in zip(gdf.latitude, 
                  gdf.longitude)]

gdf.set_geometry('polycir', inplace=True)


#You should be able to loop through the polygons and find the geometries that overlap with 
# gdf_filtered = gdf[gdf.polycir.within(gdf.iloc[0,4])]     
#导入模块
将numpy作为np导入
作为pd进口熊猫
作为gpd导入geopandas
从geopandas导入GeoDataFrame,GeoSeries
从shapely导入几何体
从shapely.geometry导入多边形,点
从functools导入部分
进口pyproj
从shapely.ops导入变换
#函数在半径上创建多边形
def polycir(纬度、经度、半径):
局部方位投影=“”+proj=aeqd+R=6371000+units=m+lat\u 0={}+lon\u 0=
{}”“。格式(lat,lon)
wgs84_至_aeqd=部分(
pyproj.transform,
pyproj.Proj(“+Proj=longlat+datum=WGS84+no_defs”),
pyproj.Proj(局部方位投影),
)
aeqd_至_wgs84=部分(
pyproj.transform,
pyproj.Proj(局部方位投影),
pyproj.Proj(“+Proj=longlat+datum=WGS84+no_defs”),
)
中心=点(浮动(lon)、浮动(lat))
转换点=转换(wgs84到aeqd,中心)
缓冲区=点\u变换。缓冲区(半径)
#获取具有lat-lon坐标的多边形
圆\多边形=变换(aeqd \ U到\ U wgs84,缓冲区)
返回圆
#将df转换为gdf
gdf=gpd.GeoDataFrame(df,geometry=gpd.points_from_xy(df.经度,df.纬度))
#创建圆形多边形
gdf['polycir']=[polycir(x,y,)表示拉链中的x,y(gdf纬度,
经度)]
gdf.set_几何体('polycir',in place=True)
#您应该能够在多边形中循环并找到与多边形重叠的几何体
#gdf_filtered=gdf[gdf.polycir.within(gdf.iloc[0,4])]

什么是“足够小”和“太远”?请提供更多数据-方法关键取决于簇的不同程度如何创建多边形,通过凸包或沿着原始序列点?KMeans要求您知道要检测多少簇。通常对多个k值运行k-means,并使用一些标准来选择一些最佳k值。当然,您需要定义“最优”的标准。OP没有说明何时应拆分群集,大小。。。这是什么措施。