mirror of
https://github.com/ada-dmitry/IRFM.git
synced 2026-09-24 09:20:36 +00:00
22 KiB
22 KiB
In [1]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import pearsonr, spearmanr, kendalltau
import sqlite3
import kagglehub
/home/ada/Documents/Files/files_mephi/Работы/ИРФМ/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html from .autonotebook import tqdm as notebook_tqdm
In [2]:
# https://www.kaggle.com/datasets/ziya07/financial-transaction-dataset-for-risk-prediction?select=financial_transactions.csv
dataset_dir = kagglehub.dataset_download(
"mchirico/montcoalert",
output_dir="../data/montcoalert",
# force_download=True, # раскомментируйте, если нужно перекачать датасет
)
print("Path to dataset files:", dataset_dir)
Path to dataset files: ../data/montcoalert
In [3]:
import os
df = pd.read_csv(os.path.join(dataset_dir, "911.csv"))
df
In [4]:
df = df.drop(columns=['desc', 'zip', 'addr', 'e'])
df['town'] = df['twp']
df = df.drop(columns=['twp'])
df
In [5]:
df.isnull().sum()
lat 0 lng 0 title 0 timeStamp 0 town 293 dtype: int64
In [6]:
df = df.dropna()
df.isnull().sum()
lat 0 lng 0 title 0 timeStamp 0 town 0 dtype: int64
In [7]:
df.describe()
# штат Пенсильвания (PA) находится примерно в следующих координатах:
# Широта (lat): от 39.7° N до 42.5° N
# Долгота (lng): от -80.5° W до -74.7° W
In [8]:
df_clean = df[
(df['lat'].between(39.7, 42.5)) &
(df['lng'].between(-80.5, -74.7))
]
df_clean.describe()
In [9]:
df_grouped = df_clean.groupby('town').size().reset_index(name='count')
df_grouped = df_grouped[df_grouped['count'] >= 5]
df_grouped.sort_values(by='count', ascending=False)
In [10]:
plt.figure(figsize=(8, 6))
sns.boxplot(y=df_grouped['count'])
plt.title('Распределение количества вызовов по городам')
plt.ylabel('Количество вызовов')
plt.show()
In [11]:
df_grouped.describe()
In [12]:
df_grouped = df_grouped.sort_values(by='count')
counts = df_grouped['count'].values
towns = df_grouped['town'].values
n = len(counts)
total_range = counts.max() - counts.min() # Размах
gap_threshold = 0.1 * total_range # Порог
# Отсекаем нижние и верхние 10% по порядку наблюдений
bottom_10_idx = int(n * 0.10)
top_10_idx = int(n * 0.90)
towns_to_drop = set()
# Проверка нижних 10% (идем от центра к краям)
# Ищем разрыв между y (индекс i) и соседом ближе к центру (индекс i+1)
for i in range(bottom_10_idx, -1, -1): # (6, 5, 4, 3, 2, 1, 0)
if i + 1 < n:
gap = counts[i+1] - counts[i]
if gap > gap_threshold:
# Нашли разрыв. Удаляем всё от y до края
for j in range(i, -1, -1):
towns_to_drop.add(towns[j])
break
# Проверка верхних 10% (идем от центра к краям)
# Ищем разрыв между y (индекс i) и соседом ближе к центру (индекс i-1)
for i in range(top_10_idx, n):
if i - 1 >= 0:
gap = counts[i] - counts[i-1]
if gap > gap_threshold:
# Нашли разрыв. Удаляем всё от y до края
for j in range(i, n):
towns_to_drop.add(towns[j])
break
towns_to_drop
{'LOWER MERION'}
In [13]:
df_clean = df_clean[~df_clean['town'].isin(towns_to_drop)]
df_clean.info()
<class 'pandas.DataFrame'> Index: 607557 entries, 0 to 663520 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 lat 607557 non-null float64 1 lng 607557 non-null float64 2 title 607557 non-null str 3 timeStamp 607557 non-null str 4 town 607557 non-null str dtypes: float64(2), str(3) memory usage: 27.8 MB
In [14]:
df_clean_grouped = df_clean.groupby('town').size().reset_index(name='count')
plt.figure(figsize=(8, 6))
sns.boxplot(y=df_clean_grouped['count'])
plt.title('Распределение количества вызовов по городам')
plt.ylabel('Количество вызовов')
plt.show()
In [15]:
df_clean_grouped.describe()
In [16]:
df_clean['timeStamp'] = pd.to_datetime(df_clean['timeStamp'])
df_clean.info()
<class 'pandas.DataFrame'> Index: 607557 entries, 0 to 663520 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 lat 607557 non-null float64 1 lng 607557 non-null float64 2 title 607557 non-null str 3 timeStamp 607557 non-null datetime64[us] 4 town 607557 non-null str dtypes: datetime64[us](1), float64(2), str(2) memory usage: 27.8 MB
In [17]:
df_clean['hour'] = df_clean['timeStamp'].dt.hour
df_clean.head()
In [18]:
calls_by_hour = df_clean.groupby('hour').size().reset_index(name='count')
calls_by_hour.head()
In [19]:
plt.figure(figsize=(10, 6))
sns.lineplot(x='hour', y='count', data=calls_by_hour, marker='o', label='Calls Count')
plt.title('Общее количество вызовов 911 по часам суток')
plt.xlabel('Час суток')
plt.ylabel('Количество вызовов')
plt.xticks(calls_by_hour['hour'])
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()
In [20]:
def analyze_correlations(df, col1, col2):
x = df[col1].values
y = df[col2].values
results = {
'Пирсон': pearsonr(x, y),
'Спирмен': spearmanr(x, y),
'Кендалл': kendalltau(x, y)
}
for method, (corr, p_value) in results.items():
abs_corr = abs(corr)
if method == 'Кендалл':
thresholds = [0.2, 0.4, 0.6, 0.8]
else:
thresholds = [0.3, 0.5, 0.7, 0.9]
if abs_corr < thresholds[0]:
strength = "слабая (или отсутствует)"
elif abs_corr < thresholds[1]:
strength = "умеренная"
elif abs_corr < thresholds[2]:
strength = "заметная"
elif abs_corr < thresholds[3]:
strength = "высокая"
else:
strength = "весьма высокая"
status = "Значима" if p_value < 0.05 else "НЕ значима"
direction = "положительная" if corr > 0 else "отрицательная"
print(f"[{method}]")
print(f" Коэффициент: {corr:.4f} ({direction})")
print(f" P-value: {p_value:.4e} ({status})")
if p_value < 0.05:
print(f" Вывод: Наблюдается {strength} связь.")
else:
print(f" Вывод: Недостаточно данных для подтверждения связи.")
print("-" * 40)
analyze_correlations(calls_by_hour, 'hour', 'count')
[Пирсон] Коэффициент: 0.5114 (положительная) P-value: 1.0638e-02 (Значима) Вывод: Наблюдается заметная связь. ---------------------------------------- [Спирмен] Коэффициент: 0.4991 (положительная) P-value: 1.3028e-02 (Значима) Вывод: Наблюдается умеренная связь. ---------------------------------------- [Кендалл] Коэффициент: 0.3623 (положительная) P-value: 1.2905e-02 (Значима) Вывод: Наблюдается умеренная связь. ----------------------------------------
In [24]:
conn = sqlite3.connect('../data/calls.db')
df_clean.to_sql('calls', conn, if_exists='replace', index=False)
conn.close()
In [25]:
conn = sqlite3.connect('../data/calls.db')
query = "SELECT * FROM calls LIMIT 5"
curr = conn.cursor()
data = curr.execute(query).fetchall()
conn.close()
data
[(40.2978759, -75.5812935, 'EMS: BACK PAINS/INJURY', '2015-12-10 17:10:52', 'NEW HANOVER', 17), (40.2580614, -75.2646799, 'EMS: DIABETIC EMERGENCY', '2015-12-10 17:29:21', 'HATFIELD TOWNSHIP', 17), (40.1211818, -75.3519752, 'Fire: GAS-ODOR/LEAK', '2015-12-10 14:39:21', 'NORRISTOWN', 14), (40.116153, -75.343513, 'EMS: CARDIAC EMERGENCY', '2015-12-10 16:47:36', 'NORRISTOWN', 16), (40.251492, -75.6033497, 'EMS: DIZZINESS', '2015-12-10 16:56:52', 'LOWER POTTSGROVE', 16)]