如何 select 基于数组的 (geo)pandas 数据帧中的多行或传播聚类算法结果的元数据?

How to select multiple rows from a (geo)pandas dataframe based on an array or propagate metadata of a clustering algorithm result?

我有一个包含多边形的 geopandas 数据框,region_id 和 center_point 纬度和经度,看起来像这样:

然后我想根据中心点对每个区域进行聚类并执行以下操作:

#Set Up
kms_per_radian = 6371.0088
eps = 0.1/kms_per_radian
coords = blocks_meta.as_matrix(columns=['lat', 'lon'])

#Cluster
from sklearn.cluster import DBSCAN

db = DBSCAN(eps=epsilon, algorithm='ball_tree', metric='haversine', min_samples=1).fit(coords)
labels = db.labels_
clusters = pd.Series([coords[labels == n] for n in range(len(set(labels)))])

这会产生一组中心点簇,如下所示。

array([[ 0.0703843 ,  0.170845  ],
       [ 0.07037922,  0.17084981],
       [ 0.07036705,  0.17085678],
       [ 0.0703715 ,  0.17083775]]) 

我正在努力弄清楚如何做的是让 regions_ids 与每个集群相关联以合并多边形以创建一个更大的区域,而无需循环遍历每个集群以及每个纬度、经度对和查询数据框。

是否有传播 ID 或查询每个集群的数据帧的方法?

如有任何帮助,我们将不胜感激。

谢谢!

编辑

我想避免的是这样做:

clusters_of_regions = []

for cluster in clusters:
    cluster_of_regions_ids = []
    for entry in cluster:
        print(cluster[0][0])
        region_id = blocks_meta.loc[blocks_meta['lat'] == cluster[0][0]]['region_id'][1]
        cluster_of_regions_ids.append(region_id)
    clusters_of_regions.append(cluster_of_regions_ids)

两者都是为了避免嵌套的 for 循环 - 每当我尝试时,我都会不断收到关键错误:

有没有一种方法可以使用中心点作为属性对区域本身进行聚类。

谢谢

我认为您的群组在您的标签中。 我想你想要的是这个(我用的是labels = [1,2,3,4]):

df1 = pd.DataFrame(ar) df1.loc[:,'labels'] = pd.Series(labels) df1

这将创建一个像这样的 df :

    0   1   labels
0   0.070384    0.170845    1
1   0.070379    0.170850    2
2   0.070367    0.170857    3
3   0.070372    0.170838    4

检查来自 skleanr (https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html) 的示例。我在这里修改它以拥有一个数据框并且类似于您的示例。

from sklearn.cluster import DBSCAN 
import pandas as pd 
import numpy as np 

X = np.array([[1, 2], [2, 2], [2, 3], [8, 7], [8, 8], [25, 80]])

df = pd.DataFrame(X, index=list(range(len(X))), columns = ['col1', 'col2'])

clustering = DBSCAN(eps = 3, min_samples = 2).fit(df) 
labels = clustering.labels_ 

df = df.merge(pd.Series(labels).to_frame().rename(columns={0:'clusters'}), left_index = True, right_index = True, how = 'outer')

df

给你:

        col1    col2    clusters
     0  1        2       0
     1  2        2       0
     2  2        3       0
     3  8        7       1
     4  8        8       1
    5   25      80      -1

根据描述:

labels_ : array, shape = [n_samples] Cluster labels for each point in the dataset given to fit(). Noisy samples are given the label -1.

在示例中,您得到两个组(标签 0 和 1)。 -1 是一个 'noisy' 样本,这里的样本明显大于其他样本。

如果你做类似的事情,你可以将你的 regions_id 和标签放在一起,比较是否存在 1:1 关系。