LoginSignup
0
1

Pythonでボロノイ図の作成

Posted at

~これまでのロードマップ~

某東京都カーディーラーのWEBサイトをスクレイピング → GeoCodingで緯度・経度取得 → foliumでロケーションマップ作成 → 今回

【ボロノイ図の生成】

前回つくった東京都カーディーラーのロケーションマップに
scipy.spatial import Voronoiを使ってボロノイ図を追加していきます。

緯度・経度の入るcsvファイルをGoogleDriveに置き、Google Colaboratoryで実行しています。

SCVファイルのカラムはA列Shop Name{i}、B列Address、C列Latitude{i}、D列Longitude{i} ×10となっていて、{i}には1~10が入ります。

import pandas as pd
import folium
from scipy.spatial import Voronoi
import numpy as np
from chardet.universaldetector import UniversalDetector

csv_file_path = 'GoogleDriveのファイルパス'

detector = UniversalDetector()
with open(csv_file_path, 'rb') as file:
    for line in file:
        detector.feed(line)
        if detector.done:
            break
detector.close()
encoding = detector.result['encoding']

df = pd.read_csv(csv_file_path, encoding='shift_jis')

m = folium.Map(location=[df['Latitude1'].mean(), df['Longitude1'].mean()], zoom_start=10)

colors = ['green', 'blue', 'gray', 'red', 'purple', 'lightblue', 'pink', 'orange', 'lightgray', 'lightgreen']

for i in range(1, 11):
    lat_col = f'Latitude{i}'
    lon_col = f'Longitude{i}'
    filtered_df = df.dropna(subset=[lat_col, lon_col])
    for _, row in filtered_df.iterrows():
        lat = row[lat_col]
        lon = row[lon_col]
        
        popup_text = row[f'Shop Name{i}']
        icon_color = colors[(i - 1) % len(colors)]
        folium.Marker(
            [lat, lon],
            tooltip=row[f'Address{i}'],
            icon=folium.Icon(color=icon_color),
            popup=popup_text
        ).add_to(m)

points = []
for i in range(1, 9):
    lat_col = f'Latitude{i}'
    lon_col = f'Longitude{i}'
    filtered_df = df.dropna(subset=[lat_col, lon_col])
    lat_lon = filtered_df[[lat_col, lon_col]].values
    points.extend(lat_lon.tolist())

vor = Voronoi(points)

encoded_polygons = []
for region in vor.regions:
    if not -1 in region and len(region) > 0:
        polygon = [vor.vertices[i] for i in region]
        encoded_polygons.append(polygon)

for region in encoded_polygons:
    polygon = np.array(region)
    folium.Polygon(
        locations=polygon,
        color='blue',
        fill=True,
        fill_color='blue',
        fill_opacity=0.4
    ).add_to(m)

vor = Voronoi(points)

map_bounds = m.get_bounds()
map_width = map_bounds[1][1] - map_bounds[0][1]
map_height = map_bounds[1][0] - map_bounds[0][0]

filtered_edges = []
for edge in vor.ridge_vertices:
    if -1 not in edge:
        x0, y0 = vor.vertices[edge[0]]
        x1, y1 = vor.vertices[edge[1]]
        if (x0 >= map_bounds[0][1] and x0 <= map_bounds[1][1] and y0 >= map_bounds[0][0] and y0 <= map_bounds[1][0]) or (x1 >= map_bounds[0][1] and x1 <= map_bounds[1][1] and y1 >= map_bounds[0][0] and y1 <= map_bounds[1][0]):
            filtered_edges.append(edge)

html = '<div style="position: absolute; left: 20px; top: -300px; white-space: nowrap; font-size: 15px; color: black;">GREEN=外車<br>BLUE=レクサス<br>GRAY=スバル<br>PURPLE=マツダ<br>LIGHTBLUE=スズキ<br>PINK=ダイハツ<br>ORANGE=トヨタ<br>RED=三菱<br>lightgray=ホンダ<br>lightgreen=日産</div>'
marker = folium.Marker(
    [df['Latitude1'].mean(), df['Longitude1'].mean()],
    icon=folium.DivIcon(html=html)
)

marker.add_to(m)

m.save('生成するファイル名.html')

スクリーンショット 2023-11-11 115748.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1