Pandas. Отношение максимальной дисперсии к минимальной
Прохожу курс Python для анализа данных и никак не могу понять в чем ошибка в решении.
Суть задачи: Создайте новый столбец - mcc_code+tr_type, сконкатенировав значения из соответствующих столбцов. (*) Оставьте только наблюдения с отрицательным значением amount. Посчитайте дисперсию по категориям получившегося столбца mcc_code+tr_type, в которых количество наблюдений >= 10. Определите отношение максимальной дисперсии к минимальной. Выведите ответ в виде вещественного числа, округлённого до ближайшего целого в формате "123456" без дробной части.
Пояснения: (*) Для конкатенации значений в столбцах можно использовать метод .astype(str) для серии и складывать соответствующие серии. Либо же применять apply к строкам датафрейма, прописывая логику преобразования и конкатенации значений внутри.
(**) Для одновременного подсчета количества наблюдений и дисперсии по категориям можно воспользоваться функцией .agg()
Исходные данные:
Мое решение задачи: вначале требуется объединить 4 таблицы с разными данными, но с общими столбцами
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
df = pd.read_csv(r'C:\Users\akuma\Documents\Jupiter_Anaconda\transactions.csv',
sep=',', nrows=1000000)
types = pd.read_csv(r'C:\Users\akuma\Documents\Jupiter_Anaconda\types.csv',
sep=';')
mcc_codes = pd.read_csv(r'C:\Users\akuma\Documents\Jupiter_Anaconda\tr_mcc_codes.csv',
sep=';')
train = pd.read_csv(r'C:\Users\akuma\Documents\Jupiter_Anaconda\gender_train.csv',
sep=',')
df_1 = df.merge(types, how='inner')
df_2 = df_1.merge(mcc_codes, how='inner')
df_3 = df_2.merge(train, how='left') # базовая таблица
После получения базовой таблицы примерно такого содержания, с ней уже работаем по задаче.
извините что картинка, не разобрался как вставлять сюда датафрейм.
df_3['mcc_code+tr_type'] = df_3[['mcc_code','tr_type']]
df_3.info()
df_3.query('amount < 0').groupby(['mcc_code+tr_type'])['amount'] \
.agg(['count', 'var']) \
.query('count >= 10')['var'] \
.agg(lambda x: round(max(x) / min(x)))
появляется ошибка при объединении столбцов mcc_code+tr_type , может где-то ошибку допустил? Понимаю, что пишу код ещё плохо и мудрено )
Ответы (3 шт):
Как делать конкатенцию указано в пояснении.
Пояснения: (*) Для конкатенации значений в столбцах можно использовать метод .astype(str) для серии и складывать соответствующие серии. Либо же применять apply к строкам датафрейма, прописывая логику преобразования и конкатенации значений внутри.
df_3['mcc_code+tr_type'] = df_3['mcc_code'].astype(str)+df_3['tr_type'].astype
Попробуйте так:
df["mcc_code+tr_type"] = df["mcc_code"].astype(str) + df["tr_type"].astype(str)
res = (df
.query("amount < 0")
.groupby("mcc_code+tr_type")
["amount"]
.agg(lambda x: x.var()**2 if len(x)>=10 else np.nan).dropna())
ratio = round(res.max() / res.min())
Для разннообразия решений:
df['mcc_code+tr_type'] = df.mcc_code.map(str) + df.tr_type.map(str)
df = df[['mcc_code+tr_type', 'amount']][df.amount < 0]
fltr = lambda group_df: len(group_df['amount']) >= 10
amount = (df.groupby('mcc_code+tr_type').filter(fltr)
.groupby('mcc_code+tr_type').var()).amount
np.rint( amount.max() / amount.min()).astype(int)
p.s.:
Решение @MaxU элегантно, но дисперсия это просто var() (!=var()**2)
Из описания перого задания (ну и в целом ищи std vs var):
"Дисперсия рассчитывается с помощью функции из библиотеки numpy:
np.var( , ddof=0) или встроенной в python функции: .var(ddof=1)",
хотя и они ошиблись если планировали тот же результат
np.var(df.s, ddof=0) != df.s.var(ddof=1)
[numpy и pandas имеют разные значения ddof по умолчанию (на сегодя),
но разница в методике незначительна]