Функция, возвращающая словарь, неправильно работает с методом groupby в панд

#python #pandas #dataframe

Вопрос:

Я хочу вычислить процентное распределение по элементам и получить выходной словарь, состоящий из time_key ключей и словаря с процентом элементов в качестве значения

Я написал этот код

 def class_distr(x):
    fractions = x.value_counts(normalize=True) # use value_counts normalize instead
    return [dict(zip(fractions.keys(), fractions.tolist()))]

def get_dict(df, col):
    grouped = df[['time_key', col]].groupby('time_key')[col].apply(lambda x: class_distr(x)).reset_index(name=col)
    return {key: value for key, value in zip(grouped['time_key'], grouped[col])} 
 

Вот фрейм данных:

 d = {'time_key': {9394: '2019-03-01',
  898: '2018-09-01',
  2398: '2018-10-01',
  5906: '2018-12-01',
  2343: '2018-10-01',
  8225: '2019-02-01',
  5506: '2018-12-01',
  6451: '2019-01-01',
  2670: '2018-10-01',
  3497: '2018-10-01'},
 'target': {9394: 3,
  898: 4,
  2398: 0,
  5906: 3,
  2343: 4,
  8225: 1,
  5506: 0,
  6451: 0,
  2670: 0,
  3497: 2}}

df = pd.DataFrame(d)
get_dict(df, 'target')
 

Выход

 {'2018-09-01': [{4: 1.0}],
 '2018-10-01': [{0: 0.5, 2: 0.25, 4: 0.25}],
 '2018-12-01': [{3: 0.5, 0: 0.5}],
 '2019-01-01': [{0: 1.0}],
 '2019-02-01': [{1: 1.0}],
 '2019-03-01': [{3: 1.0}]}
 

Видно, что внутренние словари заключены в квадратные скобки.
Мне это не нужно, но class_distr функция неправильно работает без скобок в сочетании с groupby .
Как я могу справиться с этим без дополнительного цикла для извлечения словарей из скобок?

Ответ №1:

Мы можем group к тому target времени в столбце time_key внутри dict понимания выполнить итерацию по группам и создать пары ключ-значение, где ключ-это метка времени, а значение-нормализованное распределение target для соответствующей метки времени

 grp = df.groupby('time_key')['target']
{k: g.value_counts(normalize=True).to_dict() for k, g in grp}
 

 {'2018-09-01': {4: 1.0},
 '2018-10-01': {0: 0.5, 4: 0.25, 2: 0.25},
 '2018-12-01': {0: 0.5, 3: 0.5},
 '2019-01-01': {0: 1.0},
 '2019-02-01': {1: 1.0},
 '2019-03-01': {3: 1.0}}