πŸ—Ί Π Π°Π±ΠΎΡ‚Π° с Π³Π΅ΠΎΠ΄Π°Π½Π½Ρ‹ΠΌΠΈ Π² Python ΠΈ Jupyter

Π‘Ρ‚Ρ€ΠΎΠΈΠΌ ΠΊΠ°Ρ€Ρ‚Ρƒ бСсплатных Ρ‚ΠΎΡ‡Π΅ΠΊ доступа Wi-Fi Π² МосквС, ΠΏΡ€ΠΎΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅ΠΌ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ московского ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π°, создаСм ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚Ρƒ Ρ€Π΅Π³ΠΈΠΎΠ½ΠΎΠ² Π Π€ ΠΈ Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Ρƒ ΡˆΡ‚Π°Ρ‚ΠΎΠ² БША ΠΏΠΎ COVID-19 с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π±Π»ΠΎΠΊΠ½ΠΎΡ‚ΠΎΠ² Jupyter, Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ pandas, gmaps, ipyleaflet ΠΈ folium.

Рассмотрим Ρ‚Ρ€ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΏΠΎ Ρ€Π°Π±ΠΎΡ‚Π΅ с Π³Π΅ΠΎΠ΄Π°Π½Π½Ρ‹ΠΌΠΈ: gmaps, ipyleaflet ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚ΡƒΡŽ ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌΠΈ – folium. ЗабСгая Π²ΠΏΠ΅Ρ€Π΅Π΄, скаТСм, Ρ‡Ρ‚ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ folium, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π² Π½Π΅ΠΉ ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹ ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ со слоями. Π’ ΠΊΠΎΠ½Ρ†Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ ссылки Π½Π° Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Ρ‹ с ΠΊΠΎΠ΄ΠΎΠΌ.

Установка Jupyter

Установим Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Ρ‹ Jupyter ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ:

pip install notebook

Запустим Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Ρ‹ Jupyter:

jupyter notebook

АвтоматичСски откроСтся страница ΠΏΠΎ адрСсу http://localhost:8888/tree. Π—Π°Ρ‚Π΅ΠΌ создадим Π½ΠΎΠ²Ρ‹ΠΉ Π±Π»ΠΎΠΊΠ½ΠΎΡ‚, ΠΊΠ»ΠΈΠΊΠ½ΡƒΠ² ΠΏΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ΅ New.

1. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° gmaps

НачнСм с простого – Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ gmaps. Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π½Π΅ΠΉ Π½ΡƒΠΆΠ΅Π½ API-ΠΊΠ»ΡŽΡ‡. Как Π΅Π³ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ Π½Π° сайтС Google Maps Platform.

Помимо gmaps Π½Π°ΠΌ понадобятся инструмСнты ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ управлСния ipywidgets, widgetsnbextension ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈ Π°Π½Π°Π»ΠΈΠ·Π° Π΄Π°Π½Π½Ρ‹Ρ… pandas. Они ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Ρ‡Π΅Ρ€Π΅Π· консоль (pip install), Ρ‚Π°ΠΊ ΠΈ прямо ΠΈΠ· Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Π° Ρ‡Π΅Ρ€Π΅Π· Π²ΠΎΡΠΊΠ»ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π·Π½Π°ΠΊ (!pip install):

!pip install gmaps
!pip install pandas
!pip install widgetsnbextension

АктивируСм Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Ρ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ:

!jupyter nbextension enable --py --sys-prefix widgetsnbextension
!jupyter nbextension enable --py --sys-prefix gmaps

1.1. ΠšΠ°Ρ€Ρ‚Π° Ρ‚ΠΎΡ‡Π΅ΠΊ WiFi

Рис. 1. ΠšΠ°Ρ€Ρ‚Π° с ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π°ΠΌΠΈ Ρ‚ΠΎΡ‡Π΅ΠΊ WiFi (gmaps)

Π—Π° основу возьмСм датасСт, Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½Π½Ρ‹ΠΉ Π½Π° ΠΏΠΎΡ€Ρ‚Π°Π»Π΅ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… ΠœΠΎΡΠΊΠ²Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ содСрТится информация ΠΎ 2.8 тыс. бСсплатных Ρ‚ΠΎΡ‡Π΅ΠΊ Wi-Fi. На ΠΊΠ°ΠΆΠ΄ΠΎΠΉ 1001-ΠΉ строчкС датасСта Π΄ΡƒΠ±Π»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ названия столбцов. Π’ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ ошибок ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Π½Π°Π±ΠΎΡ€Π° Π΄Π°Π½Π½Ρ‹Ρ…, ΡƒΠ΄Π°Π»ΠΈΠΌ эти строчки ΠΈΠ· Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. ΠžΡ‡ΠΈΡ‰Π΅Π½Π½Ρ‹ΠΉ массив доступСн Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ Π½Π° Π“ΠΈΡ‚Ρ…Π°Π±Π΅.

ΠšΠ°ΠΊΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ возьмСм ΠΈΠ· датасСта? Нам Π½ΡƒΠΆΠ½Ρ‹ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ (Latitude_WGS84, Longitude_WGS84), адрСс (Location) ΠΈ количСство Ρ‚ΠΎΡ‡Π΅ΠΊ доступа (NumberOfAccessPoints).

CΠΎΠ·Π΄Π°Π΄ΠΈΠΌ список wifi_points, состоящий ΠΈΠ· словарСй, Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… хранится Π²Ρ‹ΡˆΠ΅ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»Π΅Π½Π½Π°Ρ информация ΠΎ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠ΅. Π—Π°Ρ‚Π΅ΠΌ создадим ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список marker_coordinates с ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌΠΈ ΠΈ ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅ΠΌ элСмСнты списка ΠΈΠ· Ρ‚ΠΈΠΏΠ° строка str Π² Ρ‚ΠΈΠΏ вСщСствСнноС число float, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ – это число, Π° Π½Π΅ строчка.

wifi_gmaps.ipynb
import pandas as pd
import gmaps

file_name = 'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/data-9776-2020-12-21.csv'
df = pd.read_csv(file_name, sep=';', encoding='cp1251')

gmaps.configure(api_key='...')

wifi_points = []
i = 0
while i < len(df.index):
    wifi_points.append({'Coordinates': [df['Latitude_WGS84'][i], df['Longitude_WGS84'][i]], 'Location': df['Location'][i], 'NumberOfAccessPoints': df['NumberOfAccessPoints'][i]})
    i += 1

marker_coordinates = [wifi['Coordinates'] for wifi in wifi_points]
marker_coordinates = [[float(x) for x in y] for y in marker_coordinates] # здСсь ΠΌΡ‹ проходимся ΠΏΠΎ элСмСнтами Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… списков ΠΈ мСняСм ΠΈΡ… Ρ‚ΠΈΠΏΡ‹ со str Π½Π° float

info_box_template = """
<dl>
<dt>АдрСс:</dt><dd>{Location}</dd>
<dt>ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ Ρ‚ΠΎΡ‡Π΅ΠΊ доступа:</dt><dd>{NumberOfAccessPoints}</dd>
</dl>
"""

marker_info  = [info_box_template.format(**points) for points in wifi_points]
marker_layer = gmaps.marker_layer(marker_coordinates, info_box_content=marker_info )

fig = gmaps.figure()
fig.add_layer(marker_layer)
fig

Π—Π΄Π΅ΡΡŒ:

sep – Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ ΠΌΠ΅ΠΆΠ΄Ρƒ столбцами.
encoding – ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠ° Ρ„Π°ΠΉΠ»Π°.

info_box_template – Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ HTML-Ρ„ΠΎΡ€ΠΌΡƒ с описаниСм Ρ‚ΠΎΡ‡ΠΊΠΈ Wi-Fi.
<dl> – создаСт ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€.
<dt> – Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ.
<dd> – описаниС.

marker_info – список, содСрТащий Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ строчки с описаниСм Ρ‚ΠΎΡ‡Π΅ΠΊ Wi-Fi: адрСс Ρ‚ΠΎΡ‡ΠΊΠΈ (Location) ΠΈ количСство Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΡ… Ρ‚ΠΎΡ‡Π΅ΠΊ Wi-Fi (NumberOfAccessPoints).

marker_layer – создаСт слой ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² с ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌΠΈ.
fig = gmaps.figure() – ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΡƒΠ΅Ρ‚ созданиС ΠΊΠ°Ρ€Ρ‚Ρ‹.
fig.add_layer(marker_layer) – добавляСт слой с ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π°ΠΌΠΈ Π½Π° ΠΊΠ°Ρ€Ρ‚Ρƒ.
fig – запускаСт ΠΊΠ°Ρ€Ρ‚Ρƒ.

Ошибка Figure(layout)
Если ΠΏΡ€ΠΈ запускС Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Π° выскочила ошибка Figure(layout=FigureLayout(height='420px')), Ρ‚ΠΎ пСрСзапуститС Π±Π»ΠΎΠΊΠ½ΠΎΡ‚, Π½ΠΎ Π½Π΅ Ρ‡Π΅Ρ€Π΅Π· панСль управлСния Π±Π»ΠΎΠΊΠ½ΠΎΡ‚ΠΎΠΌ (Kernel β†’ Restart), Π° Ρ‡Π΅Ρ€Π΅Π· консоль.

2. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ipyleaflet

ipyleaflet – интСрактивная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π²ΠΈΠ΄ΠΆΠ΅Ρ‚ΠΎΠ², основанная ipywidgets. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΊΠ°Ρ€Ρ‚Ρ‹ OpenStreetMap.

Установим Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ pandas, ipyleaflet ΠΈ ipywidgets:

!pip install pandas
!pip install ipyleaflet
!pip install ipywidgets

2.1. ΠšΠ°Ρ€Ρ‚Π° Ρ‚ΠΎΡ‡Π΅ΠΊ WiFi

Рис. 2. ΠšΠ°Ρ€Ρ‚Π° с ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π°ΠΌΠΈ Ρ‚ΠΎΡ‡Π΅ΠΊ WiFi (ipyleaflet)

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΊΠ°Ρ€Ρ‚Ρƒ с Ρ‚ΠΎΡ‡ΠΊΠ°ΠΌΠΈ Wi-Fi, Π½ΠΎ ΡƒΠΆΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ipyleaflet. Π’ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ датасСтом ΠΈΠ· Ρ€Π°Π·Π΄Π΅Π»Π° ΠΏΡ€ΠΎ gmaps:

import pandas as pd
from ipywidgets import HTML
from ipyleaflet import Map, Marker, Popup

file_name = 'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/data-9776-2020-12-21.csv'
df = pd.read_csv(file_name, sep=';', encoding='cp1251')

wifi_points = []
i = 0
while i < len(df.index):
    wifi_points.append({'index': i, 'Coordinates': [df['Latitude_WGS84'][i], df['Longitude_WGS84'][i]], 'Location': df['Location'][i], 'NumberOfAccessPoints': df['NumberOfAccessPoints'][i]})
    i += 1

marker_coordinates = [wifi['Coordinates'] for wifi in wifi_points]
marker_coordinates = [[float(x) for x in y] for y in marker_coordinates]

m = Map(center=(55.753215, 37.622504), zoom=11)

markers = [Marker(location=(marker_coordinates[i])) for i in range(len(marker_coordinates))]

info_box_template = """
<dl>
<dt>АдрСс:</dt><dd>{Location}</dd>
<dt>ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ Ρ‚ΠΎΡ‡Π΅ΠΊ доступа:</dt><dd>{NumberOfAccessPoints}</dd>
</dl>
"""

locations_info  = [info_box_template.format(**point) for point in wifi_points]

for i in range(len(markers)):
    markers[i].popup = HTML(locations_info[i])
    m.add_layer(markers[i])

m

Π—Π΄Π΅ΡΡŒ:

markers – список ΠΈΠ· ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ².

locations_info – список ΠΈΠ· адрСсов ΠΈ количСства Ρ‚ΠΎΡ‡Π΅ΠΊ Wi-Fi.

for i in range(len(markers)) – ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· элСмСнтов Π½Π° ΠΊΠ°Ρ€Ρ‚Π΅ прСдставляСт ΠΈΠ· сСбя слой, поэтому напишСм Ρ†ΠΈΠΊΠ» ΡΠΎΠ·Π΄Π°ΡŽΡ‰ΠΈΠΉ Π½ΡƒΠΆΠ½ΠΎΠ΅ количСство слоСв. Один слой – ΠΎΠ΄ΠΈΠ½ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€.

m – отрисовываСт ΠΊΠ°Ρ€Ρ‚Ρƒ с ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π°ΠΌΠΈ.

Ошибка: Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Ρ‹ Π½Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ
Если Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Ρ‹ Π½Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ, пСрСзапуститС Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Ρ‹ Jupyter Ρ‡Π΅Ρ€Π΅Π· консоль.

2.2. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π°

Рис. 3. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ 5 ΠΊΠΌ московского ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π° (ipyleaflet)

ΠŸΠΎΡΡ‚Ρ€ΠΎΠΈΠΌ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ 5 ΠΊΠΌ московского ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π°: ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ipyleaflet ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Β«ΠœΡƒΡ€Π°Π²ΡŒΠΈΠ½Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒΒ» AntPath ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Ρ‹ Π‘Ρ‚Π°Ρ€Ρ‚ ΠΈ Ѐиниш!.

from ipyleaflet import AntPath, WidgetControl
from ipywidgets import IntSlider, jslink

m = Map(center=(55.718148, 37.555493), zoom=13)

marathon_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(marathon_path)

start_marker = Marker(location=(55.717435, 37.561014))
m.add_layer(start_marker)

finish_marker = Marker(location=(55.720267, 37.5558))
m.add_layer(finish_marker)

start = HTML()
finish = HTML()
start.value = "Π‘Ρ‚Π°Ρ€Ρ‚"                                                                      
finish.value = "Ѐиниш!"                                                                      
start_marker.popup = start
finish_marker.popup = finish

zoom_slider = IntSlider(description='ΠœΠ°ΡΡˆΡ‚Π°Π±:', min=11, max=15, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m

Π—Π΄Π΅ΡΡŒ:

marathon_path – ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π°.

start_marker ΠΈ finish_marker – ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² Π‘Ρ‚Π°Ρ€Ρ‚ ΠΈ Ѐиниш! соотвСтствСнно.

start.value ΠΈ finish.value – описания ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² старта ΠΈ Ρ„ΠΈΠ½ΠΈΡˆΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ появятся Π²ΠΎ Π²ΡΠΏΠ»Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌ ΠΎΠΊΠ½Π΅ ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΠΌΠ°Ρ€ΠΊΠ΅Ρ€.

zoom_slider – ΠΏΠΎΠ»Π·ΡƒΠ½ΠΎΠΊ ΠΌΠ°ΡΡˆΡ‚Π°Π±Π°.

color – Ρ†Π²Π΅Ρ‚ Π»ΠΈΠ½ΠΈΠΈ.

pulse_color – Ρ†Π²Π΅Ρ‚ Π±Π΅Π³ΡƒΡ‰ΠΈΡ… ΠΌΡƒΡ€Π°Π²ΡŒΠ΅Π².

2.3. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π° с ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ AwesomeIcon

Рис. 4. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π° с ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ AwesomeIcon (ipyleaflet)

Π—Π°ΠΌΠ΅Π½ΠΈΠΌ стандартныС ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² Π½Π° ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π° AwesomeIcon:

from ipyleaflet import AwesomeIcon

m = Map(center=(55.718148, 37.555493), zoom=14)

marathon_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(marathon_path)

start_icon = AwesomeIcon(
    name='fa-play',
    marker_color='green',
    icon_color='white'
)

start_marker = Marker(icon=start_icon, location=(55.717435, 37.561014))
start = HTML()
start.value = "Π‘Ρ‚Π°Ρ€Ρ‚"   
start_marker.popup = start
m.add_layer(start_marker)

finish_icon = AwesomeIcon(
    name='fa-stop',
    marker_color='blue',
    icon_color='black'
)

finish_marker = Marker(icon=finish_icon, location=(55.720267, 37.5558))
finish = HTML()                                                                 
finish.value = "Ѐиниш!"                                                                      
finish_marker.popup = finish
m.add_layer(finish_marker)

zoom_slider = IntSlider(description='ΠœΠ°ΡΡˆΡ‚Π°Π±:', min=11, max=17, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m

Π—Π΄Π΅ΡΡŒ:

start_icon ΠΈ finish_icon – содСрТат элСмСнты ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ AwesomeIcon.

marker_color – Ρ†Π²Π΅Ρ‚ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π°.

icon_color – Ρ†Π²Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ.

2.4. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π° с собствСнными ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ

Рис. 5. ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΌΠ°Ρ€Π°Ρ„ΠΎΠ½Π° с собствСнными ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ (ipyleaflet)

Π”ΠΎΠ±Π°Π²ΠΈΠΌ собствСнныС ΠΈΠΊΠΎΠ½ΠΊΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ модуля Icon:

from ipyleaflet import Icon
from ipywidgets import IntSlider

m = Map(center=(55.718148, 37.555493), zoom=14)

ant_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(ant_path)

start_icon = Icon(icon_url='https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/5d6126a97905792c584b1f9e18cd8dd767ba2966/start.png', icon_size=[97, 36])
start_marker = Marker(icon=start_icon, location=(55.717435, 37.561014))
start = HTML()
start.value = "Π‘Ρ‚Π°Ρ€Ρ‚"   
start_marker.popup = start
m.add_layer(start_marker)

finish_icon = Icon(icon_url='https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/5d6126a97905792c584b1f9e18cd8dd767ba2966/finish.png', icon_size=[97, 36])

finish_marker = Marker(icon=finish_icon, location=(55.720267, 37.5558))
finish = HTML()                                                                 
finish.value = "Ѐиниш!"                                                                      
finish_marker.popup = finish
m.add_layer(finish_marker)

zoom_slider = IntSlider(description='ΠœΠ°ΡΡˆΡ‚Π°Π±:', min=11, max=17, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m

Π—Π΄Π΅ΡΡŒ:

Π˜ΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ipyleaflet ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Icon, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ собствСнныС ΠΈΠΊΠΎΠ½ΠΊΠΈ.

icon_url – ссылка Π½Π° ΠΈΠΊΠΎΠ½ΠΊΡƒ.

icon_size=[x, y] – Π·Π°Π΄Π°Π΅Ρ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρ‹ ΠΈΠΊΠΎΠ½ΠΊΠΈ: x – Π΄Π»ΠΈΠ½Π°, y – высота.

2.5. ΠšΠ°Ρ€Ρ‚Π° 85 ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€

Рис. 6. ΠšΠ°Ρ€Ρ‚Π° 85 ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€ (ipyleaflet)

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΊΠ°Ρ€Ρ‚Ρƒ с 85 ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ Π Π€. ΠšΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ Π³Ρ€Π°Π½ΠΈΡ† ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² возьмСм ΠΈΠ· json-Ρ„Π°ΠΉΠ»Π°. Π”Π°Π½Π½Ρ‹Π΅ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ Π½Π° 2015 Π³ΠΎΠ΄ ΠΈ Π² Π½ΠΈΡ… Π΅ΡΡ‚ΡŒ Π΄Π΅Ρ„Π΅ΠΊΡ‚ с Чукотским Автономным ΠΎΠΊΡ€ΡƒΠ³ΠΎΠΌ, Π½ΠΎ для нашСй Π·Π°Π΄Π°Ρ‡ΠΈ – дСмонстрации возмоТностСй Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ – этого Π²ΠΏΠΎΠ»Π½Π΅ достаточно. ΠžΡ‡ΠΈΡ‰Π΅Π½Π½Π°Ρ вСрсия Π»Π΅ΠΆΠΈΡ‚ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ.

import os
import json
import random
import requests
from ipyleaflet import GeoJSON

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

m.add_layer(geo_json)

m

Π—Π΄Π΅ΡΡŒ:

load_data – функция, которая записываСт Ρ„Π°ΠΉΠ» с Π΄Π°Π½Π½Ρ‹ΠΌ Π² локальноС Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅.

random_color – функция, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‰Π°Ρ случайныС Ρ†Π²Π΅Ρ‚Π° для ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€.

style ΠΈ hover_style – Π·Π°Π΄Π°ΡŽΡ‚ графичСскоС ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ Π½Π° Π½Π΅Π³ΠΎ курсора ΠΌΡ‹ΡˆΠΈ.

2.6. Π˜Π½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Π°Ρ ΠΊΠ°Ρ€Ρ‚Π° Π Π€ (ΠΏΠΎ ΠΊΠ»ΠΈΠΊΡƒ)

Рис. 7. Π˜Π½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Π°Ρ ΠΊΠ°Ρ€Ρ‚Π° 85 ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€ (ipyleaflet)

Π‘Π΄Π΅Π»Π°Π΅ΠΌ ΠΊΠ°Ρ€Ρ‚Ρƒ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠΉ: ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΠΎΠ΄ ΠΊΠ°Ρ€Ρ‚ΠΎΠΉ появится Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π³ΠΎΡ€ΠΎΠ΄Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚Π°:

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

def handle_click(**kwargs):
    print(kwargs['feature']['properties']['name']) 
    
geo_json.on_click(handle_click)
m.add_layer(geo_json)

m

Π—Π΄Π΅ΡΡŒ:

handle_click – функция, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹.

['name'] – имя ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚Π°.

geo_json.on_click(handle_click) – ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΊ ΠΊΠ°Ρ€Ρ‚Π΅ событиС (Π²Ρ‹Π²ΠΎΠ΄ Π½Π° экран) ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚.

2.7. Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π°

Рис. 8. Π˜Π½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Π°Ρ ΠΊΠ°Ρ€Ρ‚Π° 85 ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€ (ipyleaflet)

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ handle_hover сдСлаСм Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π³ΠΎΡ€ΠΎΠ΄Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚Π° появлялось ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ курсора ΠΌΡ‹ΡˆΠΈ Π½Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚:

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

def handle_hover(**kwargs):
    print(kwargs['feature']['properties']['name']) 
    
geo_json.on_hover(handle_hover)
m.add_layer(geo_json)

m

Π—Π΄Π΅ΡΡŒ:

handle_hover – функция, ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰Π°Ρ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹.

geo_json.on_click(handle_hover) – ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΊ ΠΊΠ°Ρ€Ρ‚Π΅ событиС ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ Π½Π° ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚.

2.8. Π₯ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π° БША ΠΏΠΎ COVID-19

Рис. 9. Π₯ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° БША ΠΏΠΎ COVID-19 (ipyleaflet)

ΠŸΠΎΡΡ‚Ρ€ΠΎΠΈΠΌ Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Ρƒ (фоновая ΠΊΠ°Ρ€Ρ‚ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°) ΡˆΡ‚Π°Ρ‚ΠΎΠ² БША ΠΏΠΎ COVID-19. На Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ с Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΎΠΉ ΡΡ‚Π΅ΠΏΠ΅Π½ΡŒΡŽ насыщСнности отобраТаСтся ΠΈΠ½Ρ‚Π΅Π½ΡΠΈΠ²Π½ΠΎΡΡ‚ΡŒ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ показатСля. Π”Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ заболСваСмости возьмСм ΠΈΠ· рСпозитория унивСрситСта Π”ΠΆΠΎΠ½Π° Π₯опкинса, Π° ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ Π³Ρ€Π°Π½ΠΈΡ† ΡˆΡ‚Π°Ρ‚ΠΎΠ² с сайта Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ipyleaflet. Π‘Π»Π΅Π³ΠΊΠ° ΠΈΠ·ΠΌΠ΅Π½ΠΈΠΌ csv-Ρ„Π°ΠΉΠ», Π΄ΠΎΠ±Π°Π²ΠΈΠ² Π² Π½Π΅Π³ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ столбСц State с ΠΏΠΎΡ‡Ρ‚ΠΎΠ²Ρ‹ΠΌΠΈ сокращСниями ΡˆΡ‚Π°Ρ‚ΠΎΠ² БША (Alabama – AL ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅), Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Π»Π° связь со Π²Ρ‚ΠΎΡ€Ρ‹ΠΌ ΠΊΠ»ΡŽΡ‡ΠΎΠΌ (id) для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡˆΡ‚Π°Ρ‚Π° ΠΈΠ· json-Ρ„Π°ΠΉΠ»Π°. Π’Π°ΠΊΠΆΠ΅ ΡƒΠ΄Π°Π»ΠΈΠΌ нСсколько ΡˆΡ‚Π°Ρ‚ΠΎΠ² ΠΈΠ· csv-Ρ„Π°ΠΉΠ»Π°, Π³Ρ€Π°Π½ΠΈΡ†Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² json-Ρ„Π°ΠΉΠ»Π΅.

import ipyleaflet
from ipywidgets import link, FloatSlider
from branca.colormap import linear

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

geo_json_data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json',
    'us-states_covid.json',
     json.load)

confirmed = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv',
    '03-13-2021_covid.csv',
     pd.read_csv)

confirmed =  dict(zip(confirmed['State'].tolist(), confirmed['Confirmed'].tolist()))

layer = ipyleaflet.Choropleth(
    geo_data=geo_json_data,
    choro_data=confirmed,
    colormap=linear.YlOrRd_04,
    border_color='black',
    style={'fillOpacity': 0.8, 'dashArray': '5, 5'})

m = ipyleaflet.Map(center = (43,-100), zoom = 4)
m.add_layer(layer)
m

Π—Π΄Π΅ΡΡŒ:

geo_json_data – Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° json-Ρ„Π°ΠΉΠ»Π° с ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌΠΈ Π³Ρ€Π°Π½ΠΈΡ† ΡˆΡ‚Π°Ρ‚ΠΎΠ².

сonfirmed – Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° csv-Ρ„Π°ΠΉΠ»Π° с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΏΠΎ заболСваСмости.

confirmed = dict... – создаСт ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ с ΠΊΠ»ΡŽΡ‡Π΅ΠΌ ΠŸΠΎΡ‡Ρ‚ΠΎΠ²ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΡˆΡ‚Π°Ρ‚Π° ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½Π½Ρ‹Ρ… случаСв зараТСния.

geo_data – ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ Π³Ρ€Π°Π½ΠΈΡ† ΡˆΡ‚Π°Ρ‚ΠΎΠ².

choro_data – Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-Π΄Π°Π½Π½Ρ‹Π΅, количСство Π·Π°Π±ΠΎΠ»Π΅Π²ΡˆΠΈΡ… Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΡˆΡ‚Π°Ρ‚Π΅.

colormap – Ρ†Π²Π΅Ρ‚ ΠΈΠ· ΠΏΠ°Π»ΠΈΡ‚Ρ€Ρ‹ ColorBrewer.

3. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° folium

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ folium, которая Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π° ΠΊΠ°Ρ€Ρ‚Π°Ρ… OpenStreetMap, Π½ΠΎ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ большими возмоТностями ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с ipyleaflet.

3.1. Установка folium

Установим folium ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ:

!pip install folium

3.2. Π”Π²Π° слоя Π½Π° ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠ°Ρ€Ρ‚Π΅

Рис. 10. Π₯ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π° БША ΠΏΠΎ COVID-19 (folium). Π”Π²Π° слоя Π½Π° ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠ°Ρ€Ρ‚Π΅.

ΠŸΠΎΡΡ‚Ρ€ΠΎΠΈΠΌ ΠΊΠ°Ρ€Ρ‚Ρƒ ΠΏΠΎ COVID-19 Π² БША с двумя слоями: количСство Π·Π°Π±ΠΎΠ»Π΅Π²ΡˆΠΈΡ… Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΡˆΡ‚Π°Ρ‚Π΅ ΠΈ Π»Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ.

import folium

url = (
    "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json"
covid_csv = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv"
state_data = pd.read_csv(covid_csv)

m = folium.Map(location=[48, -102], zoom_start=3)

folium.Choropleth(
    geo_data=state_geo,
    name="ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½Π½Ρ‹Π΅ случаи зараТСния",
    data=state_data,
    columns=["State", "Confirmed"],
    key_on="feature.id",
    fill_color="YlOrBr",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½Π½Ρ‹Π΅ случаи зараТСния",
).add_to(m)

print()

folium.Choropleth(
    geo_data=state_geo,
    name="Π›Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ",
    data=state_data,
    columns=["State", "Case_Fatality_Ratio"],
    key_on="feature.id",
    fill_color="Reds",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Π›Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ",
    show = False,  
).add_to(m)

folium.LayerControl().add_to(m)

m

Π—Π΄Π΅ΡΡŒ:

folium.Choropleth – ΠΈΠΌΠΏΠΎΡ€Ρ‚ модуля для построСния ΠΊΠ°Ρ€Ρ‚Ρ‹.

columns – столбцы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ для построСния ΠΊΠ°Ρ€Ρ‚Ρ‹.

key – ΠΊΠ»ΡŽΡ‡, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ для построСния ΠΊΠ°Ρ€Ρ‚Ρ‹. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ id.

name – Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΊΠ°Ρ€Ρ‚Ρ‹.

fill_color – Ρ†Π²Π΅Ρ‚ ΠΈΠ· ΠΏΠ°Π»ΠΈΡ‚Ρ€Ρ‹ ColorBrewer. Если Π΄Π°Π½Π½Ρ‹Ρ… Π² столбцС Π½Π΅Ρ‚ (NaN), Ρ‚ΠΎ Ρ†Π²Π΅Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ сСрый.

legend_name – описаниС ΠΏΠΎΠ΄ шкалой.

show – опрСдСляСт, ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π»ΠΈ слой ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ ΠΊΠ°Ρ€Ρ‚Ρ‹. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ True.

Рис. 11. Π₯ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π° БША ΠΏΠΎ COVID-19 (folium). Π”Π²Π° слоя Π½Π° ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠ°Ρ€Ρ‚Π΅.

3.3. ДобавляСм ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²: Π²ΡΠΏΠ»Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ тСкст

Рис. 12. Π˜Π½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Π°Ρ Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Π° БША ΠΏΠΎ COVID-19 (folium)

Π‘Π΄Π΅Π»Π°Π΅ΠΌ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ курсора ΠΌΡ‹ΡˆΠΈ Π½Π° ΡˆΡ‚Π°Ρ‚ всплывало Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΡˆΡ‚Π°Ρ‚Π°:

url = (
    "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json"
covid_csv = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv"
state_data = pd.read_csv(covid_csv)

m = folium.Map(location=[48, -102], zoom_start=3)

covid_map = folium.Choropleth(
    geo_data=state_geo,
    name="ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½Π½Ρ‹Π΅ случаи зараТСния",
    data=state_data,
    columns=["State", "Confirmed"],
    key_on="feature.id",
    fill_color="YlOrBr",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½Π½Ρ‹Π΅ случаи зараТСния",
).add_to(m)

folium.LayerControl().add_to(m)

covid_map.geojson.add_child(folium.features.GeoJsonTooltip(['name',], labels=False))

m

Π—Π΄Π΅ΡΡŒ:

covid_map.geojson.add_child... – добавляСт Π²ΡΠΏΠ»Ρ‹Π²Π°ΡŽΡ‰Π΅Π΅ окошко с Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ ΡˆΡ‚Π°Ρ‚Π°.

3.4. Π”Π²Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠΊΠ½Π΅

Рис. 13. Π”Π²Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠΊΠ½Π΅ (folium).

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π΄Π²Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠΊΠ½Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠ»Π°Π³ΠΈΠ½Π° DualMap. Для этого Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΊ основной ΠΊΠ°Ρ€Ρ‚Π΅ m Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ ΠΊΠ°Ρ€Ρ‚Ρ‹ m1 ΠΈ m2 Ρ‡Π΅Ρ€Π΅Π· запись m.m1 ΠΈ m.m2 соотвСтствСнно:

from folium import plugins

m = plugins.DualMap(location=(59.93863, 30.31413), tiles=None, zoom_start=11)

folium.TileLayer("openstreetmap").add_to(m)
folium.TileLayer("Stamen Terrain").add_to(m.m1)
folium.TileLayer("cartodbpositron").add_to(m.m2)


figure_both = folium.FeatureGroup(name="ΠœΠ΅Ρ‚ΠΊΠ° Π½Π° ΠΎΠ±Π΅ΠΈΡ… ΠΊΠ°Ρ€Ρ‚Π°Ρ…").add_to(m)
figure_1 = folium.FeatureGroup(name="ΠœΠ΅Ρ‚ΠΊΠ° слСва").add_to(m.m1)
figure_2 = folium.FeatureGroup(name="ΠœΠ΅Ρ‚ΠΊΠ° справа").add_to(m.m2)

icon_red = folium.Icon(color="green")
folium.Marker((59.93863, 30.31413), tooltip="ΠœΠ΅Ρ‚ΠΊΠ° Π½Π° ΠΎΠ±Π΅ΠΈΡ… ΠΊΠ°Ρ€Ρ‚Π°Ρ…", icon=icon_red).add_to(figure_both)
folium.Marker((59.912563, 30.32413), tooltip="ΠœΠ΅Ρ‚ΠΊΠ° слСва").add_to(figure_1)
folium.Marker((59.93463, 30.38413), tooltip="ΠœΠ΅Ρ‚ΠΊΠ° справа").add_to(figure_2)

folium.LayerControl(collapsed=False).add_to(m)

m

Π—Π΄Π΅ΡΡŒ:

folium.TileLayer(" ") – добавляСт Π½Π° ΠΊΠ°Ρ€Ρ‚Ρƒ картографичСский слой. Π’ нашСм случаС: openstreetmap, Stamen Terrain ΠΈ cartodbpositron.

m.m1 ΠΈ m.m2 – создаСт Π΄Π²Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹: пСрвая ΠΊΠ°Ρ€Ρ‚Π° (слСва) ΠΈ вторая ΠΊΠ°Ρ€Ρ‚Π° (справа).

.add_to(m), .add_to(m.m1), .add_to(m.m2) – Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Ρ‹ Π½Π° ΠΎΠ±Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚Ρƒ ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° Π²Ρ‚ΠΎΡ€ΡƒΡŽ соотвСтствСнно.

3.5. Π“Ρ€ΡƒΠΏΠΏΠΈΡ€ΡƒΠ΅ΠΌ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Ρ‹

Рис. 14. Π“Ρ€ΡƒΠΏΠΏΠΈΡ€ΡƒΠ΅ΠΌ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Ρ‹ Π² (folium)

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΈ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΈΡ… видимости:

m = folium.Map(location=[59.93863, 30.31413], zoom_start=12)

figure = folium.FeatureGroup(name="ВсС ΠΌΠ΅Ρ‚ΠΊΠΈ")
m.add_child(figure)

group1 = plugins.FeatureGroupSubGroup(figure, "ΠŸΠ΅Ρ€Π²Π°Ρ Π³Ρ€ΡƒΠΏΠΏΠ°")
m.add_child(group1)

group2 = plugins.FeatureGroupSubGroup(figure, "Вторая Π³Ρ€ΡƒΠΏΠΏΠ°")
m.add_child(group2)

folium.Marker([59.93863, 30.31413]).add_to(group1)
folium.Marker([59.95863, 30.31413]).add_to(group1)

folium.Marker([59.94863, 30.32513]).add_to(group2)
folium.Marker([59.91763, 30.31413]).add_to(group2)

folium.LayerControl(collapsed=False).add_to(m)

m

Π—Π΄Π΅ΡΡŒ:

plugins.FeatureGroupSubGroup(figure, "name") – создаСт Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² с ΠΈΠΌΠ΅Π½Π΅ΠΌ name.

m.add_child(group1) – добавляСт Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² Π½Π° ΠΊΠ°Ρ€Ρ‚Ρƒ.

folium.Marker([59.93863, 30.31413]).add_to(group1) – добавляСт ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ Π² Π³Ρ€ΡƒΠΏΠΏΡƒ.

***

ΠœΡ‹ ΠΏΡ€ΠΎΠ΄Π΅Π»Π°Π»ΠΈ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΈ познакомились с трСмя гСографичСскими Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌΠΈ: gmaps, ipyleaflet ΠΈ folium. Π‘ ΠΈΡ… ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½Π°ΡƒΡ‡ΠΈΠ»ΠΈΡΡŒ:

  • ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π½Π° ΠΊΠ°Ρ€Ρ‚Ρƒ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Ρ‹, Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… ΠΈ ΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€ΠΎΠ² Π½Π° собствСнныС;
  • Π²Ρ‹Π΄Π΅Π»ΡΡ‚ΡŒ Π½Π° ΠΊΠ°Ρ€Ρ‚Π΅ Π³Ρ€Π°Π½ΠΈΡ†Ρ‹ ΡΡƒΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π Π€ ΠΈ ΡˆΡ‚Π°Ρ‚ΠΎΠ² БША;
  • Ρ€ΠΈΡΠΎΠ²Π°Ρ‚ΡŒ Ρ…ΠΎΡ€ΠΎΠΏΠ»Π΅Ρ‚-ΠΊΠ°Ρ€Ρ‚Ρ‹;
  • ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠΊΠ½Π΅ Π΄Π²Π΅ ΠΊΠ°Ρ€Ρ‚Ρ‹;
  • Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ json- ΠΈ csv-Ρ„Π°ΠΉΠ»Ρ‹.
***

Π‘Π»ΠΎΠΊΠ½ΠΎΡ‚Ρ‹

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ

  • ДокумСнтация gmaps.
  • ДокумСнтация ipyleaflet.
  • ДокумСнтация folium.

Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅




Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

admin
11 дСкабря 2018

ООП Π½Π° Python: ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python допускаСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΠΈ, Π½ΠΎ Π² Π΅Π³ΠΎ основС...
admin
28 июня 2018

3 самых Π²Π°ΠΆΠ½Ρ‹Ρ… сфСры примСнСния Python: возмоТности языка

БущСствуСт мноТСство областСй примСнСния Python, Π½ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ½ особСнно...
admin
13 фСвраля 2017

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python: ΠΎΡ‚ Π½ΠΎΠ²ΠΈΡ‡ΠΊΠ° Π΄ΠΎ профСссионала

Пошаговая инструкция для всСх, ΠΊΡ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒΒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python...