Расчет среднего количества покупок клиентов за год, в который вступил R - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть следующий фрейм данных в R, который представляет количество покупок в год в течение четырех лет для 4 клиентов.Переменная member_since показывает год, когда клиент присоединился к компании.

id<-c(1,2,3,4)
member_since<-c(2014,2016,2015,2014)
X2014<-c(2,0,0,3)
X2015<-c(3,0,4,2)
X2016<-c(3,2,3,4)
X2017<-c(2,3,6,0)
df<-data.frame(id,member_since,X2014,X2015,X2016,X2017)

 id    member_since X2014 X2015 X2016 X2017
 1         2014      2     3     3     2
 2         2016      0     0     2     3
 3         2015      0     4     3     6
 4         2014      3     2     4     0

Теперь я пытаюсь создать новую переменную mean_purchase, чтобы вычислить среднее количество покупок в год для каждого покупателя за год, к которому он присоединился.Это означает, например, что для customer 2 общее количество покупок должно быть разделено на 2, но для customer 4 сумма покупок должна быть разделена на 4.

 id    member_since X2014 X2015 X2016 X2017 mean_purchase
 1         2014      2     3     3     2         2.5
 2         2016      0     0     2     3         2.5
 3         2015      0     4     3     6         4.33
 4         2014      3     2     4     0         2.25

Буду признателен вам за помощь в этом.

Ответы [ 5 ]

0 голосов
/ 24 апреля 2018

Можно использовать tidyr::gather и dplyr::filter, чтобы рассчитать mean только для лет после member_since. Реализация может быть как:

library(tidyverse)

df %>% gather(year, value, -id, -member_since) %>%
  filter(member_since <= as.numeric(gsub("^X(\\d+)","\\1",year))) %>%
  group_by(id) %>%
  summarise(mean = mean(value)) %>%
  right_join(df, by="id") %>%
  select(-mean, mean) %>% as.data.frame()

#   id member_since X2014 X2015 X2016 X2017 mean
# 1  1         2014     2     3     3     2 2.50
# 2  2         2016     0     0     2     3 2.50
# 3  3         2015     0     4     3     6 4.33
# 4  4         2014     3     2     4     0 2.25
0 голосов
/ 24 апреля 2018

Мы заменяем на NA нерелевантные нули (и я предлагаю вам сохранить их в таком виде), затем мы используем rowMeans.

df[-(1:2)][t(apply(df[-(1:2)],1,cumsum))==0] <- NA
df$mean_purchase <- rowMeans(df[-(1:2)],na.rm=T)

#   id member_since X2014 X2015 X2016 X2017 mean_purchase
# 1  1         2014     2     3     3     2      2.500000
# 2  2         2016    NA    NA     2     3      2.500000
# 3  3         2015    NA     4     3     6      4.333333
# 4  4         2014     3     2     4     0      2.250000

# If you really don't want to keep NAs :
df[is.na(df)] <- 0 
0 голосов
/ 24 апреля 2018

Другое решение с apply

df$mean_purchase <- apply(df[3:6], 1, function(x) mean(x[min(which(x != 0)):length(x)]))
df$mean_purchase
# [1] 2.500000 2.500000 4.333333 2.250000
0 голосов
/ 24 апреля 2018

Основываясь на ответе Акруна, приведем небольшое обобщение, если вы хотите включить случаи, когда клиент присоединился к программе, но ничего не покупал в первый год (ы), используя mapply.

mapply(function(x,y) round(mean(unlist(df[x,(3+y):6])),2), 
       1:nrow(df), df$member_since - 2014)
# [1] 2.50 2.50 4.33 2.25
0 голосов
/ 24 апреля 2018

Мы можем использовать apply

df$mean_purchase <- apply(df[3:6], 1, function(x) round(sum(x)/sum(cumsum(x > 0) > 0), 2))
df$mean_purchase
#[1] 2.50 2.50 4.33 2.25

Или используйте rowCumsums из matrixStats

library(matrixStats)
rowSums(df[3:6])/rowSums(rowCumsums(+(df[3:6] > 0)) > 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...