Как я могу отредактировать этот фрейм данных, чтобы объединить списки словарей двух столбцов? - PullRequest
1 голос
/ 28 февраля 2020

У меня есть такой фрейм данных.

ID  Name id2                            name2                  name3
101  A    [{'a': '1'}, {'b': '2'}]  [{'e': '4'}, {'f': '5'}]  [{'x': '4'}, {'y': '5'}]
103  B    [{'c': '3'},{'d': '6'}]   [{'g': '7'},{'h': '8'}]   [{'t': '4'}, {'o': '5'}]

, и я хочу, чтобы вывод df был таким.

ID   Name id2                                                                name2
101  A    [{'a': '1','e': '4','x': '4'}, {'b': '2', 'f': '5','y': '5'}}]    [{'e': '4'}, {'f': '5'}]
103  B    [{'c': '3', 'g': '7','t': '4'},{'d': '6', 'h': '8','o': '5'}]    [{'e': '4'}, {'f': '5'}]

Имя столбца 3 будет таким же, как в Op I только что удалили его из образца выше. Дело в том, что даже если будет добавлено больше столбцов, его словари будут обновляться в столбце id2. Спасибо:)

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Учитывая, что ваш фрейм данных df, попробуйте это:

i=0
for i in range(0,df.shape[0]):
    df.id2[i][0].update(df.name2[i][0])
    df.id2[i][1].update(df.name2[i][1])
1 голос
/ 28 февраля 2020

Вы можете попробовать использовать collections.ChainMap в понимании списка:

Из документов ...

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

Итак, сначала мы zip столбцы вместе, затем вложенный zip, чтобы получить dicts из каждого столбца "рядом «в одном списке. Этот список передается в ChainMap, который объединяет их в один dict.

Пример

from collections import ChainMap

# Setup    
df = pd.DataFrame({'ID': [101, 103], 'Name': ['A', 'B'], 'id2': [[{'a': '1'}, {'b': '2'}], [{'c': '3'}, {'d': '6'}]], 'name2': [[{'e': '4'}, {'f': '5'}], [{'g': '7'}, {'h': '8'}]]})

df['id2'] = [[dict(ChainMap(*x)) for x in zip(i, n)]
             for i, n in zip(df['id2'], df['name2'])]

[out]

    ID Name                                           id2                     name2
0  101    A  [{'e': '4', 'a': '1'}, {'b': '2', 'f': '5'}]  [{'e': '4'}, {'f': '5'}]
1  103    B  [{'c': '3', 'g': '7'}, {'d': '6', 'h': '8'}]  [{'g': '7'}, {'h': '8'}]

Обновление

Более масштабируемое решение, если вам нужно объединить несколько столбцов, - сначала использовать DataFrame.filter, чтобы извлечь все столбцы, которые нужно объединить:

df = pd.DataFrame({'ID': [101, 103], 'Name': ['A', 'B'], 'id2': [[{'a': '1'}, {'b': '2'}], [{'c': '3'}, {'d': '6'}]], 'name2': [[{'e': '4'}, {'f': '5'}], [{'g': '7'}, {'h': '8'}]], 'name3': [[{'x': '4'}, {'y': '5'}], [{'t': '4'}, {'o': '5'}]]})

df['id2'] = [[dict(ChainMap(*y)) for y in zip(*x)]
             for x in zip(*df.filter(regex='id2|name').apply(tuple))]

[out]

    ID Name                                                               id2                     name2                     name3
0  101    A  [{'e': '4', 'x': '4', 'a': '1'}, {'b': '2', 'f': '5', 'y': '5'}]  [{'e': '4'}, {'f': '5'}]  [{'x': '4'}, {'y': '5'}]
1  103    B  [{'c': '3', 't': '4', 'g': '7'}, {'o': '5', 'd': '6', 'h': '8'}]  [{'g': '7'}, {'h': '8'}]  [{'t': '4'}, {'o': '5'}]

По сути, это то же самое, что и выше, только мы фильтруем столбцы "id" или "name" и объединяем их все.

...