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

Скажем, это фрейм данных:

First Name  Last Name   Val1 
George      Clooney      N     
George      Clooney      N   
George      Clooney      Y
George      Freeman      N
George      Freeman      N
Claire      Stark        N
Claire      Stark        Y   

Тогда цель состоит в том, чтобы произвести это:

First Name  Last Name   Val1  Total
George      Clooney      Y      3
George      Freeman      N      2
Claire      Stark        Y      2

Общее Val1 равно Y, если один из экземпляров равен Y.

Мой код выглядит так:

grouped = df.groupby(by=['First Name', 'Last Name'])

def val_func(x):
    if (x['Val1'] == 'Y').any():
    return 'Y'
    else:
    return 'N'

cumulative = grouped.apply(val_func)

Это работает, за исключением того, что cumulative имеет dtype object, и я могу получить доступ только к Val1, то есть я не могу получить доступ к First Name или Last Name (хотя когда я запускаю print(cumulative), он печатает все).

Если я попытаюсь:

df_cumulative = pd.DataFrame(cumulative)

тогда я просто получаю столбец с Y или N, но не имена.

Как это исправить? Более того, могу ли я вернуть два аргумента? один для Val1 и один для Total? или мне нужно будет запустить еще одну заявку на Total и добавить столбец в фрейм данных?

🤔 А знаете ли вы, что...
Python активно используется в научных и инженерных вычислениях.


33
2

Ответы:

Вот способ:

(df.sort_values('Val1')
 .groupby(['First Name','Last Name'])
 .agg(Val1 = ('Val1','last'),count = ('Val1','count'))
 .reset_index())

Выход:

  First Name Last Name Val1  count
0     Claire     Stark    Y      2
1     George   Clooney    Y      3
2     George   Freeman    N      2

Решено

Другой способ — использовать groupby.agg там, где вы используете max, чтобы получить «Y», если он существует (потому что Y>N), и count:

out = df.groupby(['First Name', 'Last Name'], sort=False, as_index=False)\
        .agg(Val1=('Val1', 'max'), Total=('Val1', 'count'))

Выход:

  First Name Last Name Val1  Total
0     George   Clooney    Y      3
1     George   Freeman    N      2
2     Claire     Stark    Y      2

Вы можете передать лямбду, которая выбирает на основе любых критериев, которые вы хотите. Например, следующие агрегаты «Val1» основаны на том, превышает ли количество «Y» количество «N» (если есть больше «Y», выберите «Y», иначе «N»):

out = df.groupby(['First Name', 'Last Name'], sort=False, as_index=False)\
        .agg(Val1=('Val1', lambda x: 'Y' if x.eq('Y').sum() > x.eq('N').sum() else 'N'), 
             Total=('Val1', 'count'))