用python写dbscan聚类算法,结果存为{"y":115.9053400,"x":29.1660400,"label":0},格式的json文件,然后用flask将json文件和leaflet前端结合画出聚类轨迹图
时间: 2023-12-04 18:06:12 浏览: 33
以下是一个简单的Python实现dbscan聚类算法的示例代码:
```
import json
import numpy as np
def dbscan(data, eps, min_pts):
labels = [0] * len(data)
cluster_id = 0
for i in range(len(data)):
if labels[i] != 0:
continue
neighbors = get_neighbors(data, i, eps)
if len(neighbors) < min_pts:
labels[i] = -1
else:
cluster_id += 1
expand_cluster(data, labels, i, neighbors, cluster_id, eps, min_pts)
result = []
for i in range(len(data)):
result.append({"y": data[i][0], "x": data[i][1], "label": labels[i]})
return result
def expand_cluster(data, labels, p, neighbors, cluster_id, eps, min_pts):
labels[p] = cluster_id
i = 0
while i < len(neighbors):
q = neighbors[i]
if labels[q] == -1:
labels[q] = cluster_id
elif labels[q] == 0:
labels[q] = cluster_id
q_neighbors = get_neighbors(data, q, eps)
if len(q_neighbors) >= min_pts:
neighbors = neighbors + q_neighbors
i += 1
def get_neighbors(data, p, eps):
neighbors = []
for i in range(len(data)):
if np.linalg.norm(data[p] - data[i]) < eps:
neighbors.append(i)
return neighbors
if __name__ == "__main__":
data = np.array([
[115.9053400, 29.1660400],
[115.9053500, 29.1660500],
[115.9053600, 29.1660600],
[115.9053700, 29.1660700],
[116.4053400, 29.6660400],
[116.4053500, 29.6660500],
[116.4053600, 29.6660600],
[116.4053700, 29.6660700],
[115.9053800, 29.1660800],
[115.9053900, 29.1660900],
[115.9054000, 29.1661000],
[115.9054100, 29.1661100],
[116.4053800, 29.6660800],
[116.4053900, 29.6660900],
[116.4054000, 29.6661000],
[116.4054100, 29.6661100]
])
eps = 0.001
min_pts = 2
result = dbscan(data, eps, min_pts)
with open("result.json", "w") as f:
json.dump(result, f)
```
上述代码将数据点存储在NumPy数组中,并使用eps和min_pts参数运行dbscan算法。结果将存储在result.json文件中。接下来,我们可以使用Flask将该文件提供给前端:
```
from flask import Flask, render_template, jsonify
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/data")
def data():
with open("result.json", "r") as f:
result = json.load(f)
return jsonify(result)
if __name__ == "__main__":
app.run(debug=True)
```
在上述代码中,我们定义了两个路由:/用于呈现前端页面,/data用于提供聚类结果。在data()函数中,我们读取result.json文件并以JSON格式返回结果。最后,我们可以在前端页面中使用Leaflet绘制聚类轨迹图:
```
<!DOCTYPE html>
<html>
<head>
<title>DBSCAN</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.min.css" integrity="sha512-aMxIOKjz/b9XWY+eZn1bD2e1wv8KJWn/7oF6lNrwKvN8B9o55LflfQ1QDm6wR8E2WKe6r+vT6TDTa6vJ3YjWZg==" crossorigin="anonymous" />
<style>
#mapid { height: 500px; }
.cluster-0 { color: blue; }
.cluster-1 { color: green; }
.cluster-2 { color: red; }
.cluster-3 { color: orange; }
.cluster--1 { color: gray; }
</style>
</head>
<body>
<div id="mapid"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.min.js" integrity="sha512-5ezp+ZSkbGw7e1U74DiLaZeJp04UxJzv+GK9W8X0hMkQ2GZwHJb+2KjJfzOxHM0uzcwJp6FCWqYUOZJUkGoB/g==" crossorigin="anonymous"></script>
<script>
var map = L.map('mapid').setView([29.1660400, 115.9053400], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(map);
fetch("/data")
.then(response => response.json())
.then(data => {
var clusters = {};
data.forEach(d => {
if (d.label == -1) {
L.circleMarker([d.x, d.y], { className: "cluster--1" }).addTo(map);
} else {
if (!clusters[d.label]) {
clusters[d.label] = L.layerGroup();
clusters[d.label].addTo(map);
}
L.circleMarker([d.x, d.y], { className: "cluster-" + d.label }).addTo(clusters[d.label]);
}
});
L.control.layers(null, clusters).addTo(map);
});
</script>
</body>
</html>
```
在上述代码中,我们首先定义了一个Leaflet地图并添加了一个OpenStreetMap图层。然后,我们使用fetch()函数从Flask应用程序中的/data路由获取聚类结果。在返回的数据中,我们遍历每个数据点并在地图上绘制一个圆形标记。标记的类名由聚类标签决定,为了将同一类的标记分组,我们使用了LayerGroup。最后,我们添加了一个图层控件,允许用户选择要显示的聚类组。