【问题标题】:Cluster a list of geographic points by distance and constraints按距离和约束对地理点列表进行聚类
【发布时间】:2020-04-07 04:07:20
【问题描述】:

我有一个送货应用程序,我想按位置接近度(线性距离)和最大订单数和最大总产品数(每个订单都有一定数量的产品)等限制对订单(每个订单都有一个 lat 和 lng 坐标)进行分组在一个组内。

对于邻近分组,我使用了 DBSCAN

coordinates = [[lat,lng],[lat,lng]],[lat,lng]],[lat,lng]],[lat,lng]]]
distance_matrix = squareform(pdist(coordinates, (lambda u,v: haversine(u,v))))

#eps=0.1 => 100m radius, 50m linear
db = DBSCAN(eps=0.1, min_samples=2, metric='precomputed')
results = db.fit(distance_matrix)

如何在此功能中添加约束?

除了 DBSCAN 或 HDBSCAN 之外,还有其他方法吗?

【问题讨论】:

  • 你有什么限制?
  • @GilseungAhn 组内最大订单数和组内最大产品数
  • 好吧..在这种情况下,您需要为具有约束的聚类开发一个数学模型并解决它。另外,是否有目标,例如要最小化的簇数?
  • @GilseungAhn 理想情况下,尊重所有约束并拥有最少的集群。

标签: python cluster-analysis latitude-longitude hdbscan


【解决方案1】:

这是一个有趣的问题。我想它可以通过很多不同的方式来完成。这里有一个解决方案供您考虑。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import seaborn as sns; sns.set()
import csv


df = pd.read_csv('C:\\your_path\\properties_2017.csv')
# df.head(10)
df = df.head(10000)

df.shape


df.dropna(axis=0,how='any',subset=['latitude','longitude'],inplace=True)

# Variable with the Longitude and Latitude
X=df.loc[:,['parcelid','latitude','longitude']]
X.head(10)

K_clusters = range(1,10)
kmeans = [KMeans(n_clusters=i) 

for i in K_clusters]
Y_axis = df[['latitude']]
X_axis = df[['longitude']]
score = [kmeans[i].fit(Y_axis).score(Y_axis)

for i in range(len(kmeans))] # Visualize
plt.plot(K_clusters, score)
plt.xlabel('Number of Clusters')
plt.ylabel('Score')
plt.title('Elbow Curve')
plt.show()

kmeans = KMeans(n_clusters = 10, init ='k-means++')
kmeans.fit(X[X.columns[1:3]]) # Compute k-means clustering.X['cluster_label'] = kmeans.fit_predict(X[X.columns[1:3]])centers = kmeans.cluster_centers_ # Coordinates of cluster centers.labels = kmeans.predict(X[X.columns[1:3]]) # Labels of each pointX.head(10)

X['cluster_label'] = kmeans.fit_predict(X[X.columns[1:3]])
centers = kmeans.cluster_centers_ # Coordinates of cluster centers.
labels = kmeans.predict(X[X.columns[1:3]]) # Labels of each pointX.head(10)

X.head(5)

X = X[['parcelid','cluster_label']]
X.head(5)


clustered_data = df.merge(X, left_on='parcelid', right_on='parcelid')
clustered_data.head(5)

centers = kmeans.cluster_centers_
print(centers)


X=df.loc[:,['parcelid','latitude','longitude']]
X.plot.scatter(x = 'latitude', y = 'longitude', c=labels, s=50, cmap='viridis')
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.5)


数据 = X 标签 = kmeans.labels_

plt.subplots_adjust(bottom = 0.1)
plt.scatter(data.iloc[:, 1], data.iloc[:, 2], c=kmeans.labels_, cmap='rainbow') 

for label, x, y in zip(labels, data.iloc[:, 1], data.iloc[:, 2]):
    plt.annotate(
        label,
        xy=(x, y), xytext=(-20, 20),
        textcoords='offset points', ha='right', va='bottom',
        bbox=dict(boxstyle='round,pad=0.5', fc='red', alpha=0.5),
        arrowprops=dict(arrowstyle = '->', connectionstyle='arc3,rad=0'))

plt.show()

# labels pointing to each data point (this is a big jumbled together; you should probably select fewer data points to analyze).

参考:

https://levelup.gitconnected.com/clustering-gps-co-ordinates-forming-regions-4f50caa7e4a1

数据来源:

https://www.kaggle.com/c/zillow-prize-1/data

【讨论】:

    【解决方案2】:

    不幸的是,我认为您想要的模型应该从头开始开发。

    您的问题可以建模为以下优化模型。

    目标函数:最小化簇数,K 约束 (1)每个簇的大小等于或小于S(参数) (2)每个簇的订单数等于或小于O(参数) (3) 对于样本x及其簇Ck,dist(x, Ck)是dist(x, C1), dist(x, C2), ..., dist(x, CK)中的最小值。

    解决这个问题需要付出很多努力...

    【讨论】:

      猜你喜欢
      • 2019-04-04
      • 2015-01-15
      • 1970-01-01
      • 2016-01-10
      • 2011-12-09
      • 2013-01-13
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      相关资源
      最近更新 更多