class DBSCAN(BaseEstimator, ClusterMixin):
"""Perform DBSCAN clustering from vector array or distance matrix.
DBSCAN - Density-Based Spatial Clustering of Applications with Noise.
Finds core samples of high density and expands clusters from them.
Good for data which contains clusters of similar density.
Read more in the :ref:`User Guide `.
Parameters
----------
eps : float, optional 同一个簇中样本的最大距离 默认:0.5
min_samples : int, optional 一个簇中的至少需要包含的样本数 默认:5
metric : string, or callable 最距离公式,可以用默认的欧式距离,还可以自己定义距离函数 默认:euclidean
metric_params : dict, optional 默认:None
Additional keyword arguments for the metric function.
algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, optional 最近邻搜索算法参数 默认:auto
brute是蛮力实现,
kd_tree是KD树实现,
ball_tree是球树实现,
auto则会在三种算法中做权衡,选择一个拟合最好的最优算法
leaf_size : int, optional (default = 30) 使用KD树或者球树时,停止建子树的叶子节点数量的阈值 默认:30
(最近邻搜索算法的参数)
p : float, optional 只用于闵可夫斯基距离和带权重闵可夫斯基距离中p值的选择 默认:None
p=1为曼哈顿距离, p=2为欧式距离
n_jobs : int, optional (default = 1) 使用的进程数量,默认为:1
若值为 -1,则用所有的CPU进行运算
Attributes
----------
core_sample_indices_ : 核心点的索引
因为labels_不能区分核心点还是边界点,所以需要用这个索引确定核心点
components_ : array, shape = [n_core_samples, n_features]#核心点
labels_ : array, shape = [n_samples] 每个点所属集群的标签,-1代表噪声
"""
def __init__(self, eps=0.5, min_samples=5, metric='euclidean',
metric_params=None, algorithm='auto', leaf_size=30, p=None,
n_jobs=1):
self.eps = eps
self.min_samples = min_samples
self.metric = metric
self.metric_params = metric_params
self.algorithm = algorithm
self.leaf_size = leaf_size
self.p = p
self.n_jobs = n_jobs
def fit(self, X, y=None, sample_weight=None):
"""Perform DBSCAN clustering from features or distance matrix.
Parameters
----------
X : 需要分类的数据
sample_weight : 样本点的权重
y : Ignored
"""
X = check_array(X, accept_sparse='csr')
clust = dbscan(X, sample_weight=sample_weight,
**self.get_params())
self.core_sample_indices_, self.labels_ = clust
if len(self.core_sample_indices_):
# fix for scipy sparse indexing issue
self.components_ = X[self.core_sample_indices_].copy()
else:
# no core samples
self.components_ = np.empty((0, X.shape[1]))
return self
def fit_predict(self, X, y=None, sample_weight=None):
"""Performs clustering on X and returns cluster labels.
Parameters
----------
X : array or sparse (CSR) matrix of shape (n_samples, n_features), or \
array of shape (n_samples, n_samples)
A feature array, or array of distances between samples if
``metric='precomputed'``.
sample_weight : array, shape (n_samples,), optional
Weight of each sample, such that a sample with a weight of at least
``min_samples`` is by itself a core sample; a sample with negative
weight may inhibit its eps-neighbor from being core.
Note that weights are absolute, and default to 1.
y : Ignored
Returns
-------
y : ndarray, shape (n_samples,)
cluster labels
"""
self.fit(X, sample_weight=sample_weight)
return self.labels_
测试:
import pandas as pd
from sklearn.cluster import DBSCAN
def main():
stopList= [{'id': '105792','lat': 28.571906,'lng': 112.337788},
{'id': '55792','lat': 28.573678,'lng': 112.381103},
{ 'id': '500792','lat': 28.571915,'lng': 112.337533},
{ 'id': '5000105792','lat': 28.573978,'lng': 112.35765},
{ 'id': '0105792','lat': 28.572656,'lng': 112.3366},
{'id': '50005792', 'lat': 28.578011, 'lng': 112.330688},
{'id': '5000105792', 'lat': 28.572228, 'lng': 112.335841},
{'id': '500105792', 'lat': 28.57849, 'lng': 112.3338},
{'id': '5005792', 'lat': 28.57239, 'lng': 112.336491},
{'id': '105792', 'lat': 28.577943, 'lng': 112.330995},
{'id': '792', 'lat': 28.571921, 'lng': 112.337783},
{'id': '505792', 'lat': 28.572401, 'lng': 112.3359},
{'id': '500092', 'lat': 28.569629, 'lng': 112.34005},
{'id': '50092', 'lat': 28.588048, 'lng': 112.337783},
{'id': '505792', 'lat': 28.572035, 'lng': 112.335683},
{'id': '05792', 'lat': 28.560938, 'lng': 112.378183},
{'id': '55792', 'lat': 28.544781, 'lng': 112.494936},
{'id': '505792', 'lat': 28.572296, 'lng': 112.336288},
{'id': '505792', 'lat': 28.571951, 'lng': 112.337806},
{'id': '55792', 'lat': 28.571551, 'lng': 112.32685}]
print('共有%d个点'%len(stopList))
initdata = pd.DataFrame(stopList)
scatterData = initdata[['lat', 'lng']] ## 选择需要显示的字段:经纬度
modle = DBSCAN(eps=0.0003,min_samples=2) # dbscan
resluts = modle.fit(scatterData) # 聚类
labels = resluts.labels_ # 每个点所属簇的索引构成的列表
print('labels\n', labels)
print('core_sample_indices_\n',resluts.core_sample_indices_)#核心点的索引
print('components_\n', resluts.components_) # 核心点
if __name__ == '__main__':
main()
运行结果:
共有20个点
labels
[ 0 -1 0 -1 1 -1 2 -1 1 -1 0 2 -1 -1 2 -1 -1 1 0 -1]
core_sample_indices_
[ 0 2 4 6 8 10 11 14 17 18]
components_
[[ 28.571906 112.337788]
[ 28.571915 112.337533]
[ 28.572656 112.3366 ]
[ 28.572228 112.335841]
[ 28.57239 112.336491]
[ 28.571921 112.337783]
[ 28.572401 112.3359 ]
[ 28.572035 112.335683]
[ 28.572296 112.336288]
[ 28.571951 112.337806]]