Выложу небольшое исследование по влиянию факторов на количество смертельных исходов на дорогах в России:
Импортируем библиотеки
!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 факторов на количество ДТП.
Комментарии (3)
xamal
00.00.0000 00:00Вывод: где лучше покрытие, много нарушителей и камер там и больше ДТП?
Ничего не перепутал?
Или лучше покрытие - выше скорость, камеры стоят там где много ДТП и камеры мониторят скорость и регистрируют много нарушителей.
Но скорость в статистике нигде не указывают.
8akkaunt
00.00.0000 00:00Пролистал целую простыню с надеждой увидеть ответ ПОЧЕМУ так ничего и не увидел !
Опять как обычно виноват водитель как владелец источника повышенной опасности)
CrazyElf
1) Для моделей, основанных на деревьях, скейлить признаки не нужно. 2) Вы даже не проверили - а выучилась ли чему-то ваша модель, и насколько хорошо. Может она вообще ничему не научилась, а вы пытаетесь анализировать влияние фич. Ни отложенной выборки, ни кросс-валидации, ни даже ну ладно хотя бы просто на трейне скор модели посмотреть. 3) А дальше хорошо было бы сравнить между собой модели разного вида - одинаково ли будут влиять факторы, может у разных моделей разный топ-3 факторов получится, как знать. 4) И регионы между собой тоже интересно было бы сравнить.