Python

Streamlit. Поиск кратчайшего пути

Время прочтения: 4 мин.

Самое длинное приключение начинается со слов «Я знаю короткую дорогу». Интересно о чем это? Читай дальше!

Streamlit — библиотека Python с открытым кодом. Она позволяет с легкостью создавать разные красивые веб-приложения для инженеров машинного обучения. Всего за несколько минут и пару строк кода можно создать стильные приложения.

Для установки библиотеки необходимо прописать следующее в консоли Python:

pip install streamlit

Для написания приложения достаточно выполнить пару действий:

  1. Создать Python файл, например, first_app.py
  2. Импортировать библиотеку import streamlit as st
  3. Запустить через консоль Python streamlit run first_app.py

Библиотека имеет широкий функционал и позволяет создавать графики, дашборды и карты, а также красиво визуализировать DataFrame’ы.

Примеры ниже:

Пример 1
Пример 2
Пример 3

Данные примеры требуют лишь пару строчек кода для создания.

Для того чтобы задать заголовок вашему приложению, достаточно ввести следующий код:

st.title('My first app')

Streamlit поддерживает многие популярные библиотеки для работы с данными, такие как Matplotlib, Altair, deck.gl, Pandas и другие.

Например, для визуализации DataFrame’а с библиотеки Pandas достаточно создать его, и прописать st.write():

df = pd.DataFrame({
  'first column': [1, 2, 3, 4],
  'second column': [10, 20, 30, 40]
})
st.write(df)

Получаем:

Если необходимо вывести данные в виде линейного графика, то вызываем команду:

chart_data = pd.DataFrame(
     np.random.randn(20, 3),
     columns=['a', 'b', 'c'])

st.line_chart(chart_data)

С помощью команды st.map() можно отобразить точки с координатами (широта, долгота) на карте. Пример:

df = pd.DataFrame(
    np.random.randn(100, 2) / [0.5, 0.5] + [55.5, 37.33],
    columns=['lat', 'lon'])
st.map(df)

Попробуем отобразить на карте маршруты передвижений.

Датасет был взят отсюда https://data.world/cityofaustin/azhh-4hg8

В нем содержатся маршруты мусороуборочных машин в городе Остин, США.

Будем отображать маршруты с возможностью показывать их по определенному дню недели.

Необходимые колонки из датасета:

the_geom — показывает координаты каждой точки маршрута.

GARB_DAY — отображает день недели маршрута.

Результат работы:

Карту можно приближать и отдалять, для того чтобы лучше изучить тот или иной маршрут.

Полный код программы:

import pandas as pd
import pydeck as pdk
import streamlit as st

st.title('Маршруты мусороуборочных машин в городе Остин')
#Цвета для маршрутов по дням недели
colors = {
        'Monday': [229,42,42],
        'Thursday': [98,42,229],
        'Wednesday': [42,229,61],
        'Tuesday': [221,235,23],
        'Friday': [144,108,26]
    }

#Функция которая приводит столбец с геопозицией в необходимую форму
def from_data_file(a):
    res = pd.DataFrame(columns = ['latlng1','latlng2'])
    for i in a:
        route = i.split(', ')
        for j in range(len(route)-1):
            res = res.append(pd.DataFrame(data=[[route[j], route[j+1]]], columns = res.columns))
    res['lon'] = res['latlng1'].apply(lambda x: float(x.split(' ')[0]))
    res['lat'] = res['latlng1'].apply(lambda x: float(x.split(' ')[1]))
    res['lon2'] = res['latlng2'].apply(lambda x: float(x.split(' ')[0]))
    res['lat2'] = res['latlng2'].apply(lambda x: float(x.split(' ')[1]))
    res['inbound'] = 100
    res['outbound'] = 100
    res = res.drop(['latlng1','latlng2'],1)
    res = res.reset_index(drop=True)
    return res

data = pd.read_csv('garbage-routes-1.csv')
#Удаляем ненужные символы из столбца с геопозициями
data['the_geom'] = data['the_geom'].apply(lambda x: x.replace(')','').replace('(','').replace('MULTIPOLYGON ',''))
data = data.set_index('GARB_DAY')
days = data.index.unique()
ALL_LAYERS = {}
#Добавляем слои на карту по дням недели
for i in days:
    ALL_LAYERS[i] = pdk.Layer(
        "ArcLayer",
        data = from_data_file(data['the_geom'][i]),
        get_source_position=["lon", "lat"],
        get_target_position=["lon2", "lat2"],
        get_source_color=colors[i],
        get_target_color=colors[i],
        auto_highlight=True,
        width_scale=0.001,
        get_width="outbound",
        width_min_pixels=3,
        width_max_pixels=30,    
    ),
st.sidebar.markdown('### Map Layers')
selected_layers = [
    layer for layer_name, layer in ALL_LAYERS.items()
    if st.sidebar.checkbox(layer_name, True)]
if selected_layers:
    st.pydeck_chart(pdk.Deck(
        map_style="mapbox://styles/mapbox/light-v10",
        initial_view_state={"latitude": 30.367,
                            "longitude": -97.6, "zoom": 11, "pitch": 50},
        layers=selected_layers,
    ))
else:
    st.error("Please choose at least one layer above.")

Здорово, не правда ли?! 😊

Советуем почитать