Исследование влияния различных факторов на смертность в ДТП в регионах РФ с помощью библиотеки shap python

от автора

Выложу небольшое исследование по влиянию факторов на количество смертельных исходов на дорогах в России:

Импортируем библиотеки

!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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *