Использование панд для добавления элементов списка вместе - PullRequest
0 голосов
/ 09 мая 2018

У меня есть следующий массив dicts:

items = [ 
{
    'FirstName': 'David',
    'Language': ['en',]
},
{
    'FirstName': 'David',
    'Language': ['fr',]
},

{
    'FirstName': 'David',
    'Language': ['en',]
},
{
    'FirstName': 'Bob',
    'Language': ['en',]
}
]

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

items = [ 
{
    'FirstName': 'David',
    'Language': ['en', 'fr']
},

{
    'FirstName': 'Bob',
    'Language': ['en',]
}
]

Я бы использовал SQL:

SELECT FirstName, GROUP_CONCAT(DISTINCT Language ORDER BY Language)
FROM items
GROUP BY FirstName

С помощью панд, как бы я скомбинировал это и создал группу на FirstName и получил массив уникальных языков? Вот что у меня есть:

>>> df = pandas.DataFrame(items)
>>> df.groupby('FirstName')['Language']
      .apply(lambda x: list(set(x))) # this line is off
      .reset_index()
      .to_dict(orient='records')

Ответы [ 4 ]

0 голосов
/ 09 мая 2018

Использование:

df.groupby('FirstName')['Language']\
  .apply(lambda x: list(set(x.str[0])))\
  .reset_index().to_dict('r')

Выход:

[{'FirstName': 'Bob', 'Language': ['en']},
 {'FirstName': 'David', 'Language': ['fr', 'en']}]

Создайте набор нашего первого элемента списка в каждой группе.

Задержка

%timeit df.groupby('FirstName').sum().applymap(lambda s: list(set(s)))

7,31 мс ± 534 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, по 100 циклов в каждом)

%timeit df.groupby('FirstName')['Language'].apply(lambda x: list(set(x.str[0]))).to_frame()

2,09 мс ± 207 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, по 100 циклов в каждом)

0 голосов
/ 09 мая 2018

Вы можете использовать:

df.groupby('FirstName').sum().applymap(lambda s: list(set(s)))

applymap будет применять функцию к каждому элементу, отображая список в дедуплицированный список.

In [185]: df = pd.DataFrame(items)

In [186]: df
Out[186]: 
  FirstName Language
0     David     [en]
1     David     [fr]
2     David     [en]
3       Bob     [en]

In [187]: df.groupby('FirstName').sum().applymap(lambda s: list(set(s)))
Out[187]: 
           Language
FirstName          
Bob            [en]
David      [en, fr]
0 голосов
/ 09 мая 2018

Объедините все с суммой, transform значениями для установки и затем to_dict()

>>> df.groupby('FirstName').sum()["Language"].transform(set).reset_index().to_dict(orient='records')

[{'FirstName': 'Bob', 'Language': {'en'}},
 {'FirstName': 'David', 'Language': {'en', 'fr'}}]
0 голосов
/ 09 мая 2018
from more_itertools import flatten
df.groupby('FirstName')['Language'].apply(lambda x: list(set(flatten([i for i in x]))))
.reset_index()
.to_dict(orient='records')

[{'FirstName': 'Bob', 'Language': ['en']},
 {'FirstName': 'David', 'Language': ['en', 'fr']}]

Я предполагаю, что вы продолжали получать unhashable type: 'list', поэтому я просто использую понимание списка, чтобы получить значение из него, а затем сгладить его, так как оно в итоге выглядело так после простого понимания списка:

FirstName
Bob                  [[en]]
David    [[en], [fr], [en]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...