2017-02-01 6 views
2

У меня есть dataframe df1 так:Группа списки различных строк по нескольким столбцам значения с панд

import pandas as pd 
dic = {'A':[0,0,2,2,2,1,5,5],'B':[[1,5,3,8],[1,8,7,5],[7,8,9,5],[3],[1,5,9,3],[0,3,5],[],[4,2,3,1]],'C':['a','b','c','c','d','e','f','f'],'D':['0','8','7','6','4','5','2','2']} 
df1 = pd.DataFrame(dic) 

и выглядит следующим образом:

#Initial dataframe 
    A    B C D 
0 0 [1, 5, 3, 8] a 0 
1 0 [1, 8, 7, 5] b 8 
2 2 [7, 8, 9, 5] c 7 
3 2   [3] c 6 
4 2 [1, 5, 9, 3] d 4 
5 1  [0, 3, 5] e 5 
6 5   [] f 2 
7 5 [4, 2, 3, 1] f 2 

Моя цель состоит в том, чтобы сгруппировать строки, преследующих те же значения в столбце A и C и объединить содержимое столбца B таким образом, чтобы результат выглядел следующим образом:

#My GOAL 
    A    B C 
0 0  [1, 5, 3, 8] a 
1 0  [1, 8, 7, 5] b 
2 2 [3, 7, 8, 9, 5] c 
3 2  [1, 5, 9, 3] d 
4 1  [0, 3, 5] e 
5 5  [4, 2, 3, 1] f 

Как видите, строки, имеющие одинаковые элементы в столбце A и C, сливаются, а если хотя бы один из них отличается, они остаются как есть. Моя идея состояла в том, чтобы использовать groupby и sum функции, как это:

df1.groupby(by=['A','C'],as_index=False,sort=True).sum() 

но Python возвращает сообщение об ошибке: Function does not reduce

Не могли бы вы сказать мне, что случилось с моей строки кода? Что я должен написать, чтобы достичь своей цели?

Примечание: Мне не важно, что происходит с колонкой D, которая может быть отброшена.

ответ

1

Одной из возможностей было бы придавить list списков, пока не истощается с помощью itertools.chain(*iterables)

import itertools 
df1.groupby(['A', 'C'])['B'].apply(lambda x: list(itertools.chain(*x))).reset_index() 

(или)

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

df1.groupby(by=['A','C'])['B'].apply(lambda x: x.sum()).reset_index() 

И выход:

enter image description here

По умолчанию groupby().sum() ищет числовые типы (скалярные) значения для выполнения агрегации, а не совокупность элементов, таких как, например, list.

1

Другая возможность:

df1.groupby(by=['A','C'],as_index=False,sort=True).agg({'B': lambda x: tuple(sum(x, []))}) 

Результат:

A C    B 
0 0 a  (1, 5, 3, 8) 
1 0 b  (1, 8, 7, 5) 
2 1 e  (0, 3, 5) 
3 2 c (7, 8, 9, 5, 3) 
4 2 d  (1, 5, 9, 3) 
5 5 f  (4, 2, 3, 1) 

Основанная в this answer (кажется, что списки не слишком хорошо работать с агрегацией).

Смежные вопросы