Скажем, это фрейм данных:
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 активно используется в научных и инженерных вычислениях.
Вот способ:
(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'))