Как рассчитать совокупный средний доход? Python

#python #pandas #group-by #cumulative-sum

#python #pandas #группировка по #кумулятивная сумма

Вопрос:

Я хочу создать график, который будет отображать совокупный средний доход за каждый «Год на борту» (первая транзакция клиента) за определенный период времени. Но я допускаю ошибки при группировании необходимой мне информации.

Игрушечные данные:

 dataset = {'ClientId': [1,2,3,1,2,3,1,2,3,1,2,3,4,4,4,4,4,4,4],
           'Year Onboarded': [2018,2019,2020,2018,2019,2020,2018,2019,2020,2018,2019,2020,2016,2016,2016,2016,2016,2016,2016],
           'Year': [2019,2019,2020,2019,2019,2020,2018,2020,2020,2020,2019,2020,2016,2017,2018,2019,2020,2017,2018],
           'Revenue': [100,50,25,30,40,50,60,100,20,40,100,20,5,5,8,4,10,20,8]}
df = pd.DataFrame(data=dataset)
 

Объяснение: у клиентов есть обозначенный «Год на борту», и они совершают транзакцию каждый упомянутый «Год».
Затем я подсчитываю годы, прошедшие с момента подключения клиентов, чтобы сделать мой график визуально более привлекательным.

 df['Yearsdiff'] = df['Year']-df['Year Onboarded']
 

Чтобы рассчитать совокупный средний доход, я попробовал следующие методы:

  • Первая попытка:
 df = df.join(df.groupby(['Year']).expanding().agg({ 'Revenue': 'mean'})
               .reset_index(level=0, drop=True)
               .add_suffix('_roll'))

df.groupby(['Year Onboarded', 'Year']).last().drop(columns=['Revenue'])
 

Выходные данные начинают накапливаться, но последняя строка больше не накапливается (не уверен, почему).

  • Вторая попытка:
 df.groupby(['Year Onboarded','Year']).agg('mean') 
                                     .groupby(level=[1]) 
                                     .agg({'Revenue':np.cumsum})
 

Но это не работает должным образом, я пробовал и другие способы, но не добился хороших результатов.

Чтобы визуализировать совокупный средний доход, я просто использую sns.lineplot

Моя цель — получить график, аналогичный приведенному ниже, но для этого мне сначала нужно правильно сгруппировать мои данные.

График ожидаемого результата

введите описание изображения здесь

Годы, которые мы видим на графике, представляют собой «Год на борту», а не «Год».

Может кто-нибудь помочь мне рассчитать совокупный средний доход, который работает для построения графика, подобного приведенному выше? Спасибо

Кроме того, данные, предоставленные в наборе данных toy, наверняка не дадут чего-то похожего на примерный график, но идея должна быть там.

Ответ №1:

Вот как я бы это сделал, и, учитывая, что данные об игрушках не совпадают, вероятно, следует внести некоторые изменения, но в целом:

 import seaborn as sns
df1 = df.copy() 
df1['Yearsdiff'] = df1['Year']-df1['Year Onboarded']
df1['Revenue'] = df.groupby(['Year Onboarded'])['Revenue'].transform('mean') 
#Find the average revenue per Year Onboarded
df1['Revenue'] = df1.groupby(['Yearsdiff'])['Revenue'].transform('cumsum')
#Calculate the cumulative sum of Revenue (Which is now the average per Year Onboarded) per Yearsdiff (because this will be our X-axis in the plot)   
sns.lineplot(x=df1['Yearsdiff'],y=df1['Revenue'],hue=df1['Year'])
#Finally plot the data, using the column 'Year' as hue to account for the different years.
 

Комментарии:

1. Я действительно пробовал что-то подобное, но, похоже, это не сработало. Также предполагается, что год на графике должен быть «Год на борту», я должен был упомянуть об этом, извините

Ответ №2:

Вы можете создать скользящее среднее значение следующим образом:

 df['rolling_mean'] = df.groupby(['Year Onboarded'])['Revenue'].apply(lambda x: x.rolling(10, 1).mean())

df

#     ClientId  Year Onboarded  Year  Revenue rolling_mean
# 0          1            2018  2019      100   100.000000
# 1          2            2019  2019       50    50.000000
# 2          3            2020  2020       25    25.000000
# 3          1            2018  2019       30    65.000000
# 4          2            2019  2019       40    45.000000
# 5          3            2020  2020       50    37.500000
# 6          1            2018  2018       60    63.333333
# 7          2            2019  2020      100    63.333333
# 8          3            2020  2020       20    31.666667
# 9          1            2018  2020       40    57.500000
# 10         2            2019  2019      100    72.500000
# 11         3            2020  2020       20    28.750000
# 12         4            2016  2016        5     5.000000
# 13         4            2016  2017        5     5.000000
# 14         4            2016  2018        8     6.000000
# 15         4            2016  2019        4     5.500000
# 16         4            2016  2020       10     6.400000
# 17         4            2016  2017       20     8.666667
# 18         4            2016  2018        8     8.571429
 

Комментарии:

1. Что означает (10,1) в rolling() ?

2. Окно (обязательно) и минимальные периоды (необязательно)