/
tuper
/
Coursovaya
Обзор
Документация
Войти
/
tuper
/
Coursovaya
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tabs.py
442 строки
17 KB
tuper
create: tabs.py
29 май 2026, 16:28
Верифицирован
29 май 2026, 16:28
4fc616d
Код
Авторство
О чём код?
# -*- coding: utf-8 -*- """Untitled4.ipynb Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/1i7PFid2Yf-wWMQcke0lKRf5sX9YSPVdm """ import pandas as pd import numpy as np file_path = 'bank_transactions_data_2_augmented_clean_2.csv' df = pd.read_csv(file_path) # Convert with mixed format df['TransactionDate'] = pd.to_datetime(df['TransactionDate'], format='mixed', errors='coerce') if 'PreviousTransactionDate' in df.columns: df['PreviousTransactionDate'] = pd.to_datetime(df['PreviousTransactionDate'], format='mixed', errors='coerce') else: df = df.sort_values(by=['AccountID', 'TransactionDate']) df['PreviousTransactionDate'] = df.groupby('AccountID')['TransactionDate'].shift(1) df['DayOfWeek'] = df['TransactionDate'].dt.day_name() df['Hour'] = df['TransactionDate'].dt.hour bins = [-1, 5, 11, 17, 23] labels = ['Night', 'Morning', 'Afternoon', 'Evening'] df['TimeOfDay'] = pd.cut(df['Hour'], bins=bins, labels=labels) df['HoursSinceLastTransaction'] = (df['TransactionDate'] - df['PreviousTransactionDate']).dt.total_seconds() / 3600.0 # Based on previous code snippet and common values df['LocationCategory'] = np.where(df['Channel'].isin(['online banking', 'mobile banking', 'Online']), 'Online', df['Location']) # Save the cleaned dataset output_path = 'cleaned_bank_transactions.csv' df.to_csv(output_path, index=False) print("INFO:") df.info() print("\nHEAD (New columns):") print(df[['AccountID', 'TransactionDate', 'PreviousTransactionDate', 'DayOfWeek', 'Hour', 'TimeOfDay', 'HoursSinceLastTransaction', 'LocationCategory']].head()) import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # Настройка эстетики plt.style.use('seaborn-v0_8-whitegrid') sns.set_context("notebook", font_scale=1.2) # Загружаем датасет df = pd.read_csv('cleaned_bank_transactions.csv') # 1. Определяем список числовых признаков для анализа numerical_cols = [ 'TransactionAmount', 'CustomerAge', 'TransactionDuration', 'LoginAttempts', 'AccountBalance', 'HoursSinceLastTransaction' ] # Создаем сетку графиков 2 на 3 (всего 6) fig, axes = plt.subplots(2, 3, figsize=(18, 10)) axes = axes.flatten() for i, col in enumerate(numerical_cols): axes[i].hist(df[col].dropna(), bins=30, color='royalblue', edgecolor='black', alpha=0.7) axes[i].set_title(f'Распределение: {col}') axes[i].set_xlabel('Значение') axes[i].set_ylabel('Частота') # 2. Безопасное удаление пустых графиков (если колонок меньше, чем размер сетки) for j in range(len(numerical_cols), len(axes)): fig.delaxes(axes[j]) plt.tight_layout() plt.show() # В твоем Jupyter Notebook используй show(), здесь мы сохраняем изображение # 1. Inspect the 'Channel' column to see what we are dealing with import pandas as pd import numpy as np df = pd.read_csv('cleaned_bank_transactions.csv') print("Unique values in 'Channel':", df['Channel'].unique()) # 2. Refine the logic to explicitly handle 'ATM' # We will create a 'ChannelType' column that distinguishes 'ATM', 'Online', and 'In-Person' def categorize_channel(channel): if channel == 'ATM': return 'ATM' elif channel in ['online banking', 'mobile banking', 'Online']: return 'Online' else: return 'In-Person' df['ChannelType'] = df['Channel'].apply(categorize_channel) # 3. Save the updated dataset df.to_csv('cleaned_bank_transactions_v2.csv', index=False) # 4. Let's create a scatterplot that highlights the 'ATM' channel # to confirm the user's observation about clusters import matplotlib.pyplot as plt import seaborn as sns plt.style.use('seaborn-v0_8-whitegrid') plt.figure(figsize=(10, 6)) # Plotting specifically looking at the 'ATM' channel behavior sns.scatterplot( data=df.sample(n=5000, random_state=42), x='TransactionAmount', y='AccountBalance', hue='ChannelType', style='ChannelType', alpha=0.6 ) plt.title('Распределение транзакций по типу канала (ATM vs Online vs In-Person)') plt.tight_layout() plt.savefig('channel_type_analysis.png') print("Updated dataframe with ChannelType and saved visualization.") v import pandas as pd import plotly.express as px # Load the data df = pd.read_csv('cleaned_bank_transactions.csv') # Correction: Use 'TransactionType' instead of 'Target_Transaction_Type' df_sample = df.sample(n=2000, random_state=42) fig = px.scatter(df_sample, x='AccountBalance', y='TransactionAmount', color='TransactionType', size='TransactionDuration', facet_col='Channel', # Разделение графиков по каналам hover_data=['CustomerOccupation', 'CustomerAge'], opacity=0.7, title='Интерактивный анализ с разделением по каналам' # Save as HTML to make it accessible (since fig.show() doesn't work directly here) fig.write_html('interactive_fraud_analysis.html') print("Plot saved as interactive_fraud_analysis.html") import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # Load the data df = pd.read_csv('cleaned_bank_transactions.csv') # Numerical columns identified previously numerical_cols = [ 'TransactionAmount', 'CustomerAge', 'TransactionDuration', 'LoginAttempts', 'AccountBalance', 'HoursSinceLastTransaction' ] # Generate the heatmap plt.figure(figsize=(10, 8)) # Spearman correlation handles non-linear relationships and outliers better corr_matrix = df[numerical_cols].corr(method='spearman') sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt=".2f", vmin=-1, vmax=1) plt.title('Тепловая карта корреляций числовых признаков') plt.tight_layout() # Save the plot plt.savefig('correlation_heatmap.png', dpi=150) print("Heatmap generated and saved.") import pandas as pd import seaborn as sns import matplotlib.pyplot as plt df = pd.read_csv('cleaned_bank_transactions.csv') # --- Тепловая карта 1: Корреляция --- numerical_cols = ['TransactionAmount', 'CustomerAge', 'TransactionDuration', 'LoginAttempts', 'AccountBalance', 'HoursSinceLastTransaction'] corr_matrix = df[numerical_cols].corr(method='spearman') plt.figure(figsize=(10, 8)) sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt=".2f", vmin=-1, vmax=1) plt.title('Тепловая карта корреляций') plt.tight_layout() plt.savefig('heatmap_correlation.png') plt.close() # --- Тепловая карта 2: Частота транзакций --- days_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] time_order = ['Night', 'Morning', 'Afternoon', 'Evening'] # Агрегация данных heatmap_data = df.groupby(['DayOfWeek', 'TimeOfDay']).size().reset_index(name='Count') heatmap_pivot = heatmap_data.pivot(index='DayOfWeek', columns='TimeOfDay', values='Count').fillna(0).astype(int) heatmap_pivot = heatmap_pivot.reindex(index=days_order, columns=time_order) plt.figure(figsize=(10, 6)) sns.heatmap(heatmap_pivot, annot=True, cmap='YlGnBu') plt.title('Частота транзакций по дням недели и времени суток') plt.ylabel('День недели') plt.xlabel('Время суток') plt.tight_layout() plt.savefig('heatmap_frequency.png') # 1. Подсчет и вывод количества полных дубликатов duplicates = df.duplicated().sum() print(f"Обнаружено полных дубликатов: {duplicates}") # 2. Удаление дубликатов # keep='first' — оставляет первое вхождение, удаляет остальные df = df.drop_duplicates(keep='first') # 3. Проверка результата print(f"Размер датасета после удаления дубликатов: {df.shape}") # Рассчитываем пороги для TransactionAmount Q1 = df['TransactionAmount'].quantile(0.25) Q3 = df['TransactionAmount'].quantile(0.75) IQR = Q3 - Q1 upper_bound = Q3 + 1.5 * IQR # Винзоризация: ограничиваем только столбец 'TransactionAmount' df['TransactionAmount'] = np.where(df['TransactionAmount'] > upper_bound, upper_bound, df['TransactionAmount']) print(f"Верхняя граница (Upper Bound): {upper_bound:.2f}") # 1. Активные пользователи онлайн active_online = df[(df['Channel'] == 'Online') & (df['TransactionDuration'] > 100)] print(f"Активные пользователи онлайн: {len(active_online)}") # 2. Подозрительная активность suspicious = df[df['LoginAttempts'] > 2] print(f"Подозрительная активность: {len(suspicious)}") # 3. Высокорисковые операции high_risk = df[(df['TimeOfDay'] == 'Night') & (df['TransactionAmount'] > 5000)] print(f"Высокорисковые операции: {len(high_risk)}") import numpy as np # Установка seed для воспроизводимости np.random.seed(42) # 1. Шум для TransactionDuration (std=1 - имитация погрешности в секундах) noise_duration = np.random.normal(0, 1, size=len(df)) df['TransactionDuration'] = (df['TransactionDuration'] + noise_duration).clip(lower=0) # 2. Шум для TransactionAmount (std=0.1 - имитация погрешности округления центов) noise_amount = np.random.normal(0, 0.1, size=len(df)) df['TransactionAmount'] = (df['TransactionAmount'] + noise_amount).clip(lower=0) print("Шум успешно добавлен в признаки TransactionDuration и TransactionAmount.") # Статистика ДО добавления шума (загрузи чистые данные) df_orig = pd.read_csv('cleaned_bank_transactions.csv') # Статистика ПОСЛЕ (твой df с шумом) # df - это твой датафрейм, куда ты уже добавил шум stats = pd.DataFrame({ 'Mean_Before': df_orig[['TransactionDuration', 'TransactionAmount']].mean(), 'Mean_After': df[['TransactionDuration', 'TransactionAmount']].mean(), 'Std_Before': df_orig[['TransactionDuration', 'TransactionAmount']].std(), 'Std_After': df[['TransactionDuration', 'TransactionAmount']].std() }) print(stats) import pandas as pd # Загрузка данных df = pd.read_csv('cleaned_bank_transactions.csv') # Дискретизация возраста bins = [0, 25, 40, 60, 100] labels = ['Youth', 'Adult', 'Mature', 'Senior'] df['Age_Group'] = pd.cut(df['CustomerAge'], bins=bins, labels=labels) # Проверка распределения для отчета print(df['Age_Group'].value_counts()) # 1. Список категориальных признаков, которые нужно проверить categorical_features = ['Channel', 'TransactionType', 'CustomerOccupation'] # 2. Вывод текущих уникальных значений для проверки консистентности for col in categorical_features: print(f"--- {col} ---") print(f"Уникальные значения: {df[col].unique()}") # 3. Приведение к единому формату (исправление регистра и пробелов) # Это превращает 'online ', 'Online', 'online' в единый формат 'Online' for col in categorical_features: df[col] = df[col].astype(str).str.strip().str.capitalize() # 4. Проверка после преобразований print("\n--- Проверка после преобразований ---") for col in categorical_features: print(f"Уникальные значения {col}: {df[col].unique()}") import matplotlib.pyplot as plt import seaborn as sns # Настройка стиля sns.set_theme(style="whitegrid") fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # TransactionAmount sns.histplot(df_original['TransactionAmount'], ax=axes[0, 0], color='gray', kde=True) axes[0, 0].set_title('TransactionAmount: ДО трансформаций') sns.histplot(df['TransactionAmount'], ax=axes[0, 1], color='skyblue', kde=True) axes[0, 1].set_title('TransactionAmount: ПОСЛЕ трансформаций') # TransactionDuration sns.histplot(df_original['TransactionDuration'], ax=axes[1, 0], color='gray', kde=True) axes[1, 0].set_title('TransactionDuration: ДО трансформаций') sns.histplot(df['TransactionDuration'], ax=axes[1, 1], color='salmon', kde=True) axes[1, 1].set_title('TransactionDuration: ПОСЛЕ трансформаций') plt.tight_layout() plt.show() # Сравним средние значения и дисперсию # df_orig — это твой исходный датасет (до чистки) # df — это твой итоговый датасет (после чистки) print(f"Среднее TransactionAmount (до): {df_orig['TransactionAmount'].mean():.2f}") print(f"Среднее TransactionAmount (после): {df['TransactionAmount'].mean():.2f}") print(f"Std TransactionDuration (до): {df_orig['TransactionDuration'].std():.2f}") print(f"Std TransactionDuration (после): {df['TransactionDuration'].std():.2f}") # Агрегируем данные для получения общей картины поведения по разным каналам и типам операций group_df = df.groupby(['Channel', 'TransactionType']).agg({ 'TransactionAmount': ['mean', 'sum', 'count'], 'TransactionDuration': 'mean' }).reset_index() # Переименование колонок для удобства чтения group_df.columns = ['Channel', 'TransactionType', 'Avg_Amount', 'Total_Amount', 'Count', 'Avg_Duration'] print(group_df) import matplotlib.pyplot as plt import seaborn as sns # Список категориальных столбцов, которые мы анализируем cat_cols = ['TransactionType', 'Channel', 'CustomerOccupation'] # Создаем сетку графиков fig, axes = plt.subplots(1, 3, figsize=(18, 5)) # Цикл для построения графиков for i, col in enumerate(cat_cols): # Подсчет количества каждой категории counts = df[col].value_counts() # Построение графика sns.barplot(x=counts.index, y=counts.values, ax=axes[i], palette='viridis', hue=counts.index, legend=False) # Оформление axes[i].set_title(f'Распределение: {col}', fontsize=12) axes[i].set_ylabel('Количество') axes[i].tick_params(axis='x', rotation=45) plt.tight_layout() plt.show() # Если нужно сохранить для отчета: fig.savefig('categorical_distribution.png', dpi=300) from sklearn.preprocessing import LabelEncoder # 1. Label Encoding для бинарного признака TransactionType le = LabelEncoder() df['TransactionType'] = le.fit_transform(df['TransactionType']) # 2. One-Hot Encoding для признака Channel df = pd.get_dummies(df, columns=['Channel'], prefix='Ch') # 3. Frequency Encoding для Location (высокая кардинальность) loc_freq = df['Location'].value_counts(normalize=True) df['Location_Freq'] = df['Location'].map(loc_freq) print(df.head()) # Посмотри, появились ли колонки Ch_ATM, Ch_Online и т.д. # Агрегация редких профессий threshold = 0.02 occ_counts = df['CustomerOccupation'].value_counts(normalize=True) rare_occupations = occ_counts[occ_counts < threshold].index df['CustomerOccupation'] = df['CustomerOccupation'].apply( lambda x: 'Other_Rare' if x in rare_occupations else x ) # Вывод результата для отчета print("Распределение после агрегации:") print(df['CustomerOccupation'].value_counts(normalize=True)) df['Financial_Profile'] = df['Age_Group'].astype(str) + "_" + df['AccountType'].astype(str) print(df.columns.tolist()) # Создаем новый синтетический признак df['Age_Transaction_Profile'] = df['Age_Group'].astype(str) + "_" + df['TransactionType'].astype(str) # Проверка результата print(df['Age_Transaction_Profile'].value_counts().head()) import matplotlib.pyplot as plt import seaborn as sns # Подсчет количества клиентов в каждом профиле profile_counts = df['Age_Transaction_Profile'].value_counts() # Создание визуализации plt.figure(figsize=(12, 6)) sns.barplot(x=profile_counts.index, y=profile_counts.values, palette='magma', hue=profile_counts.index, legend=False) plt.title('Распределение клиентов по финансовым профилям (Возраст + Тип транзакции)', fontsize=14) plt.xlabel('Композитный профиль') plt.ylabel('Количество транзакций') plt.xticks(rotation=45, ha='right') # Поворот подписей для читаемости plt.tight_layout() # Сохранение для отчета plt.savefig('TransactionType.png', dpi=300) plt.show() # Посмотрим, как выглядят уникальные значения в твоем новом признаке print(df['TransactionType'].unique())