функция группирования на основе нескольких строк

#python #pandas #pandas-groupby

Вопрос:

Вот мои данные:

ID Дата период счет
1 2015-01-01 начало 5
1 2015-01-15 конец 10
2 2015-01-01 начало 2
2 2015-01-07 середина_1 7
2 2015-01-14 конец 10

Это записи результатов с течением времени. Я закодировал столбец «период», чтобы вам было легко его интерпретировать.

Как я могу найти разницу или процентное изменение в баллах от начала до конца?

Если бы я это сделал pd.groupby , я мог бы найти минимальную или максимальную дату, но как бы я сопоставил это со счетом на минимальную или максимальную дату?

Мне все равно, использует ли расчет дату или период, мне просто нужно выяснить, как их сопоставить.

Мне нужны данные, которые выглядят так:

ID изменение_в_скоре_старт_то_енд
1 100%
2 400%

Ответ №1:

Вот еще один подход:

Код:

 import pandas as pd

df = pd.read_csv('test.csv')
df = df.drop('date', axis=1).set_index(['id', 'period']).unstack(1).droplevel(0 , axis=1)

df['change_in_score_start_to_end'] = ((df['end']/df['start'] -1)*100).map('{:.0f}%'.format)
print(df)
 

Выход:

 period   end  mid_1  start change_in_score_start_to_end
id                                                     
1       10.0    NaN    5.0                         100%
2       10.0    7.0    2.0                         400%
 

Ответ №2:

Одним из вариантов было бы pivot :

 new_df = df.pivot(index='id', columns='period', values='score')
 

new_df :

 period   end  mid_1  start
id                        
1       10.0    NaN    5.0
2       10.0    7.0    2.0
 

Затем вычисления можно выполнять в строках end и start столбцах:

 out = (
    (((new_df['end'] - new_df['start']) / new_df['start']) * 100)
        .map('{:.0f}%'.format)
        .reset_index(name='change_in_score_start_to_end')
)
 

out :

    id change_in_score_start_to_end
0   1                         100%
1   2                         400%
 

Полный Рабочий Пример:

 import pandas as pd

df = pd.DataFrame({
    'id': [1, 1, 2, 2, 2],
    'date': ['2015-01-01', '2015-01-15', '2015-01-01', '2015-01-07',
             '2015-01-14'],
    'period': ['start', 'end', 'start', 'mid_1', 'end'],
    'score': [5, 10, 2, 7, 10]
})

new_df = df.pivot(index='id', columns='period', values='score')
out = (
    (((new_df['end'] - new_df['start']) / new_df['start']) * 100)
        .map('{:.0f}%'.format)
        .reset_index(name='change_in_score_start_to_end')
)

print(out)