Python pandas пользовательская функция agg

Dataframe:
  one two
a  1  x
b  1  y
c  2  y
d  2  z
e  3  z

grp = DataFrame.groupby('one')
grp.agg(lambda x: ???) #or equivalent function

Желаемый вывод из grp.agg:

one two
1   x|y
2   y|z
3   z

Моя функция agg перед интеграцией данных была "|".join(sorted(set(x))). В идеале я хочу иметь любое количество столбцов в группе, а agg возвращает "|".join(sorted(set()) для каждого элемента столбца, такого как два выше. Я также пробовал np.char.join().

Love Pandas, и он взял меня из 800-строчной сложной программы на 400-строчную прогулку в парке, который увеличивает масштаб. Спасибо:)

Ответ 1

Вы были так близки:

In [1]: df.groupby('one').agg(lambda x: "|".join(x.tolist()))
Out[1]:
     two
one
1    x|y
2    y|z
3      z

Расширенный ответ на сортировку дескриптора и выполнение только набора:

In [1]: df = DataFrame({'one':[1,1,2,2,3], 'two':list('xyyzz'), 'three':list('eecba')}, index=list('abcde'), columns=['one','two','three'])

In [2]: df
Out[2]:
   one two three
a    1   x     e
b    1   y     e
c    2   y     c
d    2   z     b
e    3   z     a

In [3]: df.groupby('one').agg(lambda x: "|".join(x.order().unique().tolist()))
Out[3]:
     two three
one
1    x|y     e
2    y|z   b|c
3      z     a

Ответ 2

Существует лучший способ конкатенации строк в pandas документации. Итак, я предпочитаю этот способ:

In [1]: df.groupby('one').agg(lambda x: x.str.cat(sep='|'))
Out[1]:
     two
one
1    x|y
2    y|z
3      z

Ответ 3

Просто уточнение принятого ответа:

df.groupby('one').agg(lambda x: "|".join(x.tolist()))

Обратите внимание, что тип df.groupby('one') - SeriesGroupBy. И функция agg определена по этому типу. Если вы проверяете документацию этой функции, она говорит, что ее ввод - это функция, которая работает в Series. Это означает, что тип x в вышеприведенной лямбде - это Series.

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

def myfun1(x):
    return "|".join(x.tolist())

а потом:

df.groupby('one').agg(myfun1)