我有一个问题想了很久。这是关于人群聚集。
我有:
我有一个 pandas 数据框,其中包含
latitude
和 longitude
列,它们代表人们家的空间坐标。
这可以是一个例子:
import pandas as pd
data = {
"latitude": [49.5659508, 49.568089, 49.5686342, 49.5687609, 49.5695834, 49.5706579, 49.5711228, 49.5716422, 49.5717749, 49.5619579, 49.5619579, 49.5628938, 49.5628938, 49.5630028, 49.5633175, 49.56397639999999, 49.566359, 49.56643220000001, 49.56643220000001, 49.5672061, 49.567729, 49.5677449, 49.5679685, 49.5679685, 49.5688543, 49.5690616, 49.5713705],
"longitude": [10.9873409, 10.9894035, 10.9896749, 10.9887881, 10.9851579, 10.9853273, 10.9912959, 10.9910182, 10.9867083, 10.9995758, 10.9995758, 11.000319, 11.000319, 10.9990996, 10.9993819, 11.004145, 11.0003023, 10.9999593, 10.9999593, 10.9935709, 11.0011213, 10.9954016, 10.9982288, 10.9982288, 10.9975928, 10.9931367, 10.9939141],
}
df = pd.DataFrame(data)
df.head(11)
latitude longitude
0 49.565951 10.987341
1 49.568089 10.989403
2 49.568634 10.989675
3 49.568761 10.988788
4 49.569583 10.985158
5 49.570658 10.985327
6 49.571123 10.991296
7 49.571642 10.991018
8 49.571775 10.986708
9 49.561958 10.999576
10 49.561958 10.999576
我需要什么:
我需要将人们分成簇大小等于 9 的簇。这样我就得到了邻居簇。但是,我不希望具有“完全相同的空间坐标”的人位于同一个集群中。由于我的数据集中有超过 3000 人,因此有很多人(大约数百人)具有完全相同的空间坐标。
如何对人进行聚类?:完成聚类工作的一个很好的算法是 k 均值约束算法。正如这篇文章中所解释的,该算法允许将聚类大小设置为 9。我花了几行代码才对人员进行聚类。
问题:居住在同一栋建筑物(具有相同空间坐标)的人总是聚集到同一个集群中,因为目标是将彼此住得很近的人聚集在一起。因此我必须找到一种自动的方法,将这些人放入不同的集群中。但不仅仅是任何不同的集群,而是包含住得相对较近的人的集群(见下图)。
这张图总结了我的问题:
背景信息:这就是我对人们进行聚类的方式:
from k_means_constrained import KMeansConstrained
coordinates = np.column_stack((df["latitude"], df["longitude"]))
# Define the number of clusters and the number of points per cluster
n_clusters = len(df) // 9
n_points_per_cluster = 9
# Perform k-means-constrained clustering
kmc = KMeansConstrained(n_clusters=n_clusters, size_min=n_points_per_cluster, size_max=n_points_per_cluster, random_state=0)
kmc.fit(coordinates)
# Get cluster assignments
df["cluster"] = kmc.labels_
# Print the clusters
for cluster_num in range(n_clusters):
cluster_data = df[df["cluster"] == cluster_num]["latitude", "longitude"]
print(f"Cluster {cluster_num + 1}:")
print(cluster_data)
在此示例中,我只是将第三个特征增加 1,但如果您有大量数据并且丢失了重复项,您可能需要尝试不同的缩放因子:
# add a new feature
df['feature'] = df.groupby(['latitude', 'longitude']).cumcount()
# just for visually checking prints (can remove)
df['IsDuplicate'] = df.groupby(['latitude', 'longitude'])['feature'].transform('count') > 1
coordinates = np.column_stack((df["latitude"], df["longitude"], df['feature']))
因此,当您运行函数并打印所有列时,您可以看到重复项被分配到另一个集群:
Cluster 1:
latitude longitude feature IsDuplicate cluster
0 49.565951 10.987341 0 False 0
1 49.568089 10.989403 0 False 0
2 49.568634 10.989675 0 False 0
3 49.568761 10.988788 0 False 0
4 49.569583 10.985158 0 False 0
5 49.570658 10.985327 0 False 0
6 49.571123 10.991296 0 False 0
7 49.571642 10.991018 0 False 0
8 49.571775 10.986708 0 False 0
Cluster 2:
latitude longitude feature IsDuplicate cluster
10 49.561958 10.999576 1 True 1
12 49.562894 11.000319 1 True 1
18 49.566432 10.999959 1 True 1
19 49.567206 10.993571 0 False 1
21 49.567745 10.995402 0 False 1
23 49.567968 10.998229 1 True 1
24 49.568854 10.997593 0 False 1
25 49.569062 10.993137 0 False 1
26 49.571371 10.993914 0 False 1
Cluster 3:
latitude longitude feature IsDuplicate cluster
9 49.561958 10.999576 0 True 2
11 49.562894 11.000319 0 True 2
13 49.563003 10.999100 0 False 2
14 49.563317 10.999382 0 False 2
15 49.563976 11.004145 0 False 2
16 49.566359 11.000302 0 False 2
17 49.566432 10.999959 0 True 2
20 49.567729 11.001121 0 False 2
22 49.567968 10.998229 0 True 2