Расширение возможностей управления окружающей средой с помощью Geospatial Streamlit

Как градостроитель, я обнаружил, что Streamlit — отличный инструмент для создания интерактивных и удобных информационных панелей для демонстрации результатов машинного обучения и взаимодействия с людьми. В этом разделе я покажу вам, как я использую Streamlit для представления своих данных в геопространственном формате, уделяя особое внимание Индии.

Решения для геопространственной визуализации качества воздуха в Индии

Индия — это не только страна, богатая данными, но и быстро растущая экономика, поэтому крайне важно отслеживать факторы окружающей среды, особенно качество воздуха. Геопространственная визуализация позволяет нам легко понять эти изменения окружающей среды. 🧐

В этой статье я расскажу вам, как я использую Streamlit для создания удобных геопространственных панелей мониторинга, которые помогают нам внимательно следить за качеством воздуха и другими факторами окружающей среды. Давайте рассмотрим возможности Streamlit и геопространственной визуализации для эффективного управления окружающей средой. 😀

Получение данных геолокации: ключевой шаг

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

На этом этапе вместо инструментов Google я использовал эффективную библиотеку Goecoder. Я доверяю этой библиотеке больше, чем Google! 😁

Поверьте мне; Геокодер оказался моим лучшим выбором! 😁 Сервисы Google могут быть недоступны в некоторых странах, например в Иране. Поэтому я предпочитаю альтернативы с открытым исходным кодом, которые обеспечивают доступность для всех. 💑

Чтобы все было организовано и доступно, я сохраняю данные геолокации в файле.

from geopy.geocoders import Nominatim
import pandas as pd

path = '/air_quality_data.csv'
df = pd.read_csv(path)

unique_cities = df['City'].unique()
print("Number of unique cities:", len(unique_cities))

# Initialize the Nominatim geocoder
geolocator = Nominatim(user_agent="city_locator")

city_data = []

for city in unique_cities:
    location = geolocator.geocode(city + ', India')
    if location is not None:
        print(city, location.latitude, location.longitude)
        city_data.append({
            'City': city,
            'Latitude': location.latitude,
            'Longitude': location.longitude
        })

city_df = pd.DataFrame(city_data)
city_df.to_csv('city_coordinates.csv', index=False)

Настройте таблицу данных

Теперь, когда у нас есть данные геолокации, пришло время загрузить данные. Хотя более профессиональный способ — это кодирование, я не использовал его в этом проекте. 😅

Чтобы облегчить доступ к необходимой информации, я объединил данные геолокации с данными о качестве воздуха. ПРИСОЕДИНЯЙТЕСЬ К ЛЕВОМУ SQL! Здесь пригодятся небольшие знания SQL.

Также отображение карты обычно занимает слишком много места, я использовал кеширование, чтобы оптимизировать работу нашего приложения. Кэширование обеспечивает более плавную и быструю работу с картой. 😎

import streamlit as st
import pandas as pd
import geopandas as gpd
import folium
from streamlit_folium import folium_static
from geopy.geocoders import Nominatim
import numpy as np
from sklearn.preprocessing import LabelEncoder
# ----------- Setup the table -----------
@st.cache_data
def load_data():
    data = pd.read_csv('air_quality_data.csv')
    data['Date'] = pd.to_datetime(data['Date'], format='%m/%d/%Y').dt.date
    # le = LabelEncoder()
    # data['City_Encoded'] = le.fit_transform(data['City'])
    return data

city_coordinates = pd.read_csv('city_coordinates.csv')

def merge_data():
    air_quality_data = load_data()
    merged_data = pd.merge(air_quality_data, city_coordinates, on='City', how='left')
    return merged_data

Проектирование пользовательского интерфейса: боковая и главная панели

Для пользовательского интерфейса я использовал sidbar. Я думаю, что смогу лучше общаться с пользователями. Этот пользовательский интерфейс действительно повышает ясность моих идей и доступность информации.

На боковой панели я разместил данные о загрязнителях воздуха и дополнительную информацию, связанную с проектом. Удобная функция в Streamlit, которая мне нравится, — это Expander. 😍 Этот инструмент оказывается очень полезным, поскольку он оптимизирует использование пространства и обеспечивает легкий доступ к важной информации.

# ----------- Create a Streamlit app -----------
st.title('Air Quality Spatial Analysis')

# Filter the dataset by year
df = merge_data()  

# Sidebar for selecting date and pollutant
st.sidebar.subheader('Filter Data')
min_date = df['Date'].min()
max_date = df['Date'].max()
selected_date = st.slider('Select Date', min_date, max_date, min_date)
selected_pollutant = st.sidebar.selectbox('Select Pollutant', ['PM2.5', 'PM10', 'NO', 'NO2', 'NOx', 'NH3', 'CO', 'SO2', 'O3', 'Benzene', 'Toluene', 'Xylene'])

with st.sidebar.expander('More Information'):
    # Add an "About" subsection
    st.markdown('### About The Project')
    st.write('This project is an interactive visualization of air quality data for cities in India.')

    # Add a subsection on air quality in India
    st.markdown('### Air Quality in India')
    st.write('Air quality in India is a vital issue due to its severe health impacts, economic productivity losses and environmental degradation.')

    # Add a subsection on the source code
    st.markdown('### Clean Air for India')
    st.write('By providing accessible air quality information, I aim to enhance awareness and create a way for people to collaborate effectively.')

    # Add a subsection on the source code
    st.markdown('### Source Code')
    st.write('The code is available on GitHub: https://github.com/hsheikh7/Streamlit_Projects.')

    # Add a subsection on the source code
    st.markdown('### Data')
    st.write('The data originates from "Air Quality Data in India (2015 - 2020)" available at: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india?select=city_day.csv')

Показать карту

Теперь давайте рассмотрим ключевые особенности нашей карты:

  1. Отправная точка. Карта начинается с определения местоположения первого города в нашем наборе данных. Зум 5 в порядке. Он обеспечивает оптимальный обзор региона.
  2. Обработка данных. Я учел все отсутствующие или недоступные точки данных (NA), чтобы обеспечить плавную визуализацию карты. В аккуратной структуре мне следует разобраться с NA при настройке таблицы данных!
  3. Маркеры с цветовой кодировкой. Чтобы облегчить оценку качества воздуха, я использовал разные цвета. Красные маркеры обозначают уровни загрязнения воздуха, превышающие рекомендуемые пределы, а зеленые маркеры обозначают районы с приемлемым качеством воздуха. вы также можете изменить размер маркеров, чтобы отобразить некоторые данные! 😏
filtered_df = df[(df['Date'] == selected_date) & ~df[selected_pollutant].isna()]

city_row = df.iloc[0]  # You can choose any city as the default center
m = folium.Map(location=[city_row['Latitude'], city_row['Longitude']], zoom_start=5)

# Marker color based on pollutant value and limit
def get_marker_color(pollutant_value, limit):
    if pollutant_value <= limit:
        return 'green'
    else:
        return 'red'

# Add markers for each city to the map
for index, row in filtered_df.iterrows():
    marker_color = get_marker_color(row[selected_pollutant], limits_df.loc[limits_df['Pollutant'] == selected_pollutant, 'Limit_of_Acceptance'].values[0])
    folium.CircleMarker(
        location=[row['Latitude'], row['Longitude']],
        radius=5,
        color=marker_color,
        fill=True,
        fill_color=marker_color,
        fill_opacity=0.7,
        tooltip=f"{row['City']}: {row[selected_pollutant]}"
    ).add_to(m)

# Display the map 
st.subheader('Air Quality Map')
folium_static(m)

Пределы качества воздуха для каждого загрязнителя

pollutants = ["PM2.5", "PM10", "NO", "NO2", "NOx", "NH3", "CO", "SO2", "O3", "Benzene", "Toluene", "Xylene"]
limits = [
    12,   # PM2.5
    20,   # PM10
    40,   # NO
    40,   # NO2
    50,   # NOx
    100,  # NH3
    4.5,  # CO
    40,   # SO2
    100,  # O3
    5,    # Benzene
    10,   # Toluene
    10    # Xylene
]

limits_df = pd.DataFrame({
    "Pollutant": pollutants,
    "Limit_of_Acceptance": limits
})

Последние мысли

Давайте подведем итоги! Я просто показал, как создать интерактивное геопространственное приложение для визуализации ваших данных. Я планирую изучить такие инструменты, как Shiny и Dash, чтобы создавать еще более интерактивные и увлекательные проекты. Эти платформы предлагают потрясающие возможности для улучшения представления данных и взаимодействия с пользователем.

Спасибо, что нашли время прочитать эту статью. Надеюсь, это было информативно и вдохновило для ваших собственных проектов.

Если вы хотите углубиться в Streamlit, не стесняйтесь просмотреть мою коллекцию Проекты Streamlit на моем GitHub.

На простом английском языке

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