Фрейм данных в словарь, включая список словарей

#python #pandas #list #dataframe #dictionary

#python #pandas #Список #фрейм данных #словарь

Вопрос:

Я пытаюсь преобразовать приведенный ниже фрейм данных в словарь. Я хочу сгруппировать по столбцу A и взять список общей последовательности. например, для

Пример 1:

     n1 v1  v2 
2    A  C   3
3    A  D   4
4    A  C   5
5    A  D   6
  

Ожидаемый результат:

 {'A': [{'C':'3','D':'4'},{'C':'5','D':'6'}]}
  

Пример 2:

 n1   n2  v1  v2 
s1    A  C   3
s1    A  D   4
s1    A  C   5
s1    A  D   6
s1    B  P   6
s1    B  Q   3
  

Ожидаемый результат:

 {'s1': {'A': [{'C': 3, 'D': 4}, {'C': 5, 'D': 6}], 'B': {'P': 6, 'Q': 3}}}
  

итак, в основном C и D повторяются как последовательность, я хочу объединить C и D в один словарь и составить список, если это происходит несколько раз.

Пожалуйста, обратите внимание (в настоящее время я использую приведенный ниже код):

 def recur_dictify(frame):
    if len(frame.columns) == 1:
        if frame.values.size == 1: return frame.values[0][0]
        return frame.values.squeeze()
    grouped = frame.groupby(frame.columns[0])
    d = {k: recur_dictify(g.iloc[:,1:]) for k,g in grouped}
    return d
  

Это возвращает :

 {s1 : {'A': {'C': array(['3', '5'], dtype=object), 'D': array(['4', '6'], dtype=object),'B':{'E':'5','F':'6'}}
  

Кроме того, может быть другая серия, s2 имеющая E,F,G,E,F,G повторяющиеся, а некоторые X и Y имеющие единичные значения

Комментарии:

1. изменяется ли последовательность или всегда содержит C и D ?

2. Привет, пожалуйста, проверьте мой обновленный вопрос, возможно, вы получите больше ясности

Ответ №1:

Давайте создадим функцию, dictify которая создает словарь с ключами верхнего уровня из name столбца и записывает повторяющиеся вхождения значений в столбце v1 в разные вложенные словари:

 from collections import defaultdict

def dictify(df):
    dct = defaultdict(list)
    for k, g in df.groupby(['n1', df.groupby(['n1', 'v1']).cumcount()]):
        dct[k[0]].append(dict([*g[['v1', 'v2']].values]))
    return dict(dct)
  

 dictify(df)

{'A': [{'C': 3, 'D': 4}, {'C': 5, 'D': 6}]}
  

Обновить:

В случае, если может быть переменное количество ключей первичной группировки, т. [n1, n2, ...] мы можем использовать более общий метод:

 def update(dct, keys, val):
    k, *_ = keys
    dct[k] = update(dct.get(k, {}), _, val) if _ 
        else [*np.hstack([dct[k], [val]])] if k in dct else val
    return dct

def dictify(df, keys):
    dct = dict()
    for k, g1 in df.groupby(keys):
        for _, g2 in g1.groupby(g1.groupby('v1').cumcount()):
            update(dct, k, dict([*g2[['v1', 'v2']].values]))

    return dict(dct)
  

 dictify(df, ['n1', 'n2'])

{'s1': {'A': [{'C': 3, 'D': 4}, {'C': 5, 'D': 6}], 'B': {'P': 6, 'Q': 3}}}
  

Комментарии:

1. Привет, спасибо.. Я публикую еще один связанный вопрос ниже, пожалуйста, проверьте .. появление нескольких на самом деле не обязательно.. хочу дать для этого инструкцию if.

2. Только сейчас, пожалуйста, проверьте

3. @PriyalMangla Это совершенно другой вопрос, чем предыдущий 😉

4. Пожалуйста, проверьте мой обновленный вопрос сейчас .. в основном его динамический, те, которые имеют обновленную последовательность, должны быть в списке и не повторяться, а не в списке

5. Да, да, я знаю, на самом деле это был мой актуальный вопрос, я не мог сформулировать его раньше. Но большое спасибо за ваш ответ.. Я могу где-нибудь использовать эту логику

Ответ №2:

Вот простое однострочное утверждение, которое решает вашу проблему:

 def df_to_dict(df):
    return {name: [dict(x.to_dict('split')['data'])
                   for _, x in d.drop('name', 1).groupby(d.index // 2)]
            for name, d in df.groupby('name')}
  

Вот пример:

 df = pd.DataFrame({'name': ['A'] * 4,
                   'v1': ['C', 'D'] * 2,
                   'v2': [3, 4, 5, 6]})
print(df_to_dict(df))
  

Вывод:

 {'A': [{'C': 3, 'D': 4}, {'C': 5, 'D': 6}]}
  

Комментарии:

1. Спасибо :), я обновил свой вопрос, пожалуйста, проверьте?