Выложу небольшое исследование по влиянию факторов на количество смертельных исходов на дорогах в России:
Импортируем библиотеки
!pip install shap import shap import pandas as pd from sklearn.tree import DecisionTreeRegressor import seaborn as sns from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestRegressor !pip install reverse_geocoder import reverse_geocoder as rg import pandas as pd import numpy as np import matplotlib.pyplot as plt
Выгрузим данные и сразу обработаем их
improvement_coating = pd.read_excel('/content/drive/MyDrive/Счетная палата/ДТП/Протяженность_автомобильных_дорог_общего_пользования_с_усовершенствованным_покр.xlsx') improvement_coating = improvement_coating.rename(columns=improvement_coating.iloc[0]).drop(0, axis=0) improvement_coating.reset_index(drop=True, inplace=True) improvement_coating = improvement_coating.drop(0, axis=0) improvement_coating.reset_index(drop=True, inplace=True) improvement_coating_2021 = improvement_coating[improvement_coating.columns[-1]] improvement_coating = pd.DataFrame(data=improvement_coating[improvement_coating.columns[0]].tolist(), columns=['region_rf']).join(improvement_coating[improvement_coating.columns[2 : -1]]) improvement_coating['2021 г.'] = improvement_coating_2021 improvement_coating

road_norm = pd.read_excel('/content/drive/MyDrive/Счетная палата/ДТП/11111150300270200001_Доля_автомобильных_дорог_общего_пользования,_отвечающих_нормативным_требованиям.xlsx') road_norm = road_norm.rename(columns=road_norm.iloc[0]).drop(0, axis=0) road_norm.reset_index(drop=True, inplace=True) road_norm_2021 = road_norm[road_norm.columns[-1]] road_norm = pd.DataFrame(data=road_norm[road_norm.columns[0]].tolist(), columns=['region_rf']).join(road_norm[road_norm.columns[2 : -1]]) road_norm['2021 г.'] = road_norm_2021 road_norm

light_road = pd.read_csv('/content/drive/MyDrive/Счетная палата/скдф/Освещение дороги.csv') light_road_for_fit = light_road.query('out_value_of_the_road == "автомобильная дорога местного значения"').groupby('out_region')['out_length', 'out_defect_prop_count', 'out_ligth_prop_count', 'out_light_count'].sum().reset_index()\ .rename(columns={'out_region' : 'region_rf'}) light_road_for_fit

Датасет с данными о ДТП, сразу посчитаем количество ДТП по регионам:
df = pd.read_csv('/content/drive/MyDrive/Счетная палата/ДТП/joined.csv') df['datetime'] = pd.DatetimeIndex(df['datetime']).year df = df[df['datetime'] == 2021] df_group = df.groupby('parent_region')['dead_count'].sum()\ .to_frame()\ .reset_index()\ .rename(columns={'parent_region' : 'region_rf'}) df_group

Далее имеем такой датасет с установленными камерами на территории РФ
milestones = pd.read_csv('/content/drive/MyDrive/Счетная палата/ДТП/milestones.csv', sep=';') milestones

Нам необходимо вывести регион из координат и посчитать количество установленных камер по регионам
# Функция для определения региона по батчам def get_regions_batch(batch): coordinates = list(zip(batch['gps_y'], batch['gps_x'])) results = rg.search(coordinates) regions = [result['admin1'] for result in results] return regions # Разбиваем таблицу на батчи batches = np.array_split(milestones, 10) # Обрабатываем каждый батч отдельно batch_results = [] for batch in batches: batch_results.append(get_regions_batch(batch)) # Объединяем результаты results = [region for batch_result in batch_results for region in batch_result] milestones['region'] = results # Выводим результат milestones def translate_region(region): regions_dict = { 'Adygeya': 'Республика Адыгея', 'Altai Krai': 'Алтайский край', 'Altay': 'Республика Алтай', 'Amur': 'Амурская область', 'Arkhangelskaya': 'Архангельская область', 'Astrakhan': 'Астраханская область', 'Bashkortostan': 'Республика Башкортостан', 'Belgorod': 'Белгородская область', 'Brjansk': 'Брянская область', 'Chechnya': 'Чеченская Республика', 'Chelyabinsk': 'Челябинская область', 'Chuvashia': 'Чувашская Республика', 'Crimea': 'Республика Крым', 'Dagestan': 'Республика Дагестан', 'Heilongjiang Sheng': 'Хэйлунцзян', 'Hokkaido': 'Хоккайдо', 'Ingushetiya': 'Республика Ингушетия', 'Irkutsk': 'Иркутская область', 'Ivanovo': 'Ивановская область', 'Jaroslavl': 'Ярославская область', 'Jewish Autonomous Oblast': 'Еврейская автономная область', 'Kabardino-Balkariya': 'Кабардино-Балкарская Республика', 'Kaliningrad': 'Калининградская область', 'Kalmykiya': 'Республика Калмыкия', 'Kaluga': 'Калужская область', 'Kamtsjatka': 'Камчатский край', 'Karachayevo-Cherkesiya': 'Карачаево-Черкесская Республика', 'Kemerovo': 'Кемеровская область', 'Khabarovsk Krai': 'Хабаровский край', 'Khakasiya': 'Республика Хакасия', 'Khanty-Mansiyskiy Avtonomnyy Okrug': 'Ханты-Мансийский автономный округ', 'Kharkiv': 'Харьковская область', 'Kirov': 'Кировская область', 'Komi Republic': 'Республика Коми', 'Kostroma': 'Костромская область', 'Krasnodarskiy': 'Краснодарский край', 'Krasnoyarskiy': 'Красноярский край', 'Kurgan': 'Курганская область', 'Kursk': 'Курская область', 'Leningrad': 'Ленинградская область', 'Lipetsk': 'Липецкая область', 'Luhansk': 'не соответствует ни одному региону России или Украины в списке', 'Magadan': 'Магаданская область', 'Mariy-El': 'Республика Марий Эл', 'Misto Sevastopol': 'Республика Крым (г. Севастополь)', 'Mordoviya': 'Республика Мордовия', 'Moscow': 'г. Москва', 'Moskovskaya': 'Московская область', 'Murmansk': 'Мурманская область', 'Nenetskiy Avtonomnyy Okrug': 'Ненецкий автономный округ', 'Nizjnij Novgorod': 'Нижегородская область', 'North Ossetia': 'Республика Северная Осетия-Алания', 'Novgorod': 'Новгородская область', 'Novosibirsk': 'Новосибирская область', 'Omsk': 'Омская область', 'Orenburg': 'Оренбургская область', 'Orjol': 'Орловская область', 'Penza': 'Пензенская область', 'Perm': 'Пермский край', 'Primorskiy': 'Приморский край', 'Pskov': 'Псковская область', 'Republic of Karelia': 'Республика Карелия', 'Respublika Buryatiya': 'Республика Бурятия', 'Rjazan': 'Рязанская область', 'Rostov': 'Ростовская область', 'Sakha': 'Республика Саха (Якутия)', 'Sakhalin': 'Сахалинская область', 'Samara': 'Самарская область', 'Saratov': 'Саратовская область', 'Smolensk': 'Смоленская область', "Misto Sevastopol'": "Республика Крым", "South Karelia": "Республика Карелия", "St.-Petersburg": "Ленинградская область", "Stavropol'skiy": "Ставропольский край", "Sumy": "Нет соответствия", "Sverdlovsk": "Свердловская область", "Tambov": "Тамбовская область", "Tatarstan": "Республика Татарстан", "Tjumen": "Тюменская область", "Tomsk": "Томская область", "Transbaikal Territory": "Забайкальский край", "Tula": "Тульская область", "Tverskaya": "Тверская область", "Tyva": "Республика Тыва", "Udmurtiya": "Удмуртская Республика", "Ulyanovsk": "Ульяновская область", "Vladimir": "Владимирская область", "Volgograd": "Волгоградская область", "Vologda": "Вологодская область", "Voronezj": "Воронежская область", 'Yamalo-Nenetskiy Avtonomnyy Okrug' : 'ЯНАО'} return regions_dict.get(region, region) milestones['region'] = milestones['region'].apply(translate_region) milestones_for_fit = milestones.groupby('region')['src_camera'].count().to_frame().reset_index().rename(columns={'region' : 'region_rf', 'src_camera' : 'Количество камер'}) milestones_for_fit

count_intruder = pd.read_excel('/content/drive/MyDrive/Счетная палата/емисс/Количество нарушителей правил дорожного движения.xlsx') count_intruder

Соединим все выгруженные таблицы:
merged_table = pd.merge(df_group, light_road_for_fit, on="region_rf") merged_table = pd.merge(merged_table, road_norm[['region_rf', '2021 г.']], on="region_rf") merged_table = pd.merge(merged_table, milestones_for_fit, on="region_rf") merged_table = pd.merge(merged_table, count_intruder, on="region_rf") merged_table = pd.merge(merged_table, improvement_coating[['region_rf', '2021 г.']], on="region_rf")\ .rename(columns={'2021 г._x' : 'road_norm', '2021 г._y' : 'improvement_coating'}) merged_table = merged_table.fillna(0) merged_table

Сделаем деление на признаки и target, далее обучим модель
X = merged_table[['out_length', 'out_defect_prop_count', 'out_ligth_prop_count', 'out_light_count', 'road_norm', 'improvement_coating', 'Количество камер', 'Количество нарушителей ПДД водителей', 'Количество нарушителей ПДД пассажиров', 'Количество нарушителей ПДД пешеходов']] X = X.rename(columns={'out_length' : 'Протяженность освещения', 'out_defect_prop_count' : 'Количество опор с деффектами', 'out_ligth_prop_count' : 'Количество опор освещения', 'out_light_count' : 'Количество светильников', 'improvement_coating' : 'Усовершенствованное покрытие', 'road_norm' : 'Доля дорог, отвечающих норм-м требованиям'}) y = merged_table.dead_count scaler = StandardScaler() model = scaler.fit(X) X = model.transform(X) regr = DecisionTreeRegressor(max_depth=3, random_state=12345) model = regr.fit(X, y) X = pd.DataFrame(data=X, columns=['Протяженность освещения', 'Количество опор с деффектами', 'Количество опор освещения', 'Количество светильников', 'Доля дорог, отвечающих норм-м требованиям', 'Усовершенствованное покрытие', 'Количество камер', 'Количество нарушителей ПДД водителей', 'Количество нарушителей ПДД пассажиров', 'Количество нарушителей ПДД пешеходов']) X
Интерпретируем модель с помощью shap
def shap_feature_importance(X, y, model): """ Функция для выявления важности признаков с помощью shap_values Аргументы: X -- признаки (numpy array или pandas dataframe) y -- таргет (numpy array или pandas series) model -- обученная модель Возвращает: shap.summary_plot -- график, отображающий важность каждого признака """ # Инициализируем Explainer и вычисляем shap_values explainer = shap.Explainer(model, X) shap_values = explainer(X) # Получаем родные названия признаков feature_names = X.columns if isinstance(X, pd.DataFrame) else None # Выводим график, отображающий важность каждого признака shap.summary_plot(shap_values, X, plot_type="bar", feature_names=feature_names) # инициализируем и обучаем модель model = RandomForestRegressor(n_estimators=100, random_state=42) model.fit(X, y) shap_feature_importance(X, y, model)

Косвенно, но можем сделать вывод о влиянии топ-3 факторов на количество ДТП.
ссылка на оригинал статьи https://habr.com/ru/articles/724042/
Добавить комментарий