【问题标题】:How to calculate yearly retention rate by group in R?如何在R中按组计算年保留率?
【发布时间】:2020-11-20 21:11:14
【问题描述】:

我有一个大型数据集,其中包含多年来位于县的个人。每年,一些人搬到不同的县或离开数据集,新的人加入。 我想计算每年和第一年留在同一县的人数。这是我发现最接近这项任务的问题(没有按县进行额外分组):Month-over-month Customer Retention Rate in R

这是数据集的简化版本:

dt <- setDT(data.frame(ID = rep(c('a', 'b', 'c', 'd', 'a', 'c', 'd', 'e', 'c', 'e', 'f'),2),
                 CTY = rep(c(1, 2), each = 11),
                 YEAR = rep(c(1,1,1,1,2,2,2,2,3,3,3),2)))

到目前为止,我的解决方案依赖于循环

x =matrix(NA, 2,3)
y =matrix(NA, 2,3)
for (i in 1:2) {
  for (j in 1:3) {
    x[i,j] = ifelse(j == 1, NA, sum(dt[CTY == i & YEAR == j, ID] %in%  dt[CTY == i & YEAR == j-1, ID] == T))
    y[i,j] = ifelse(j == 1, NA, sum(dt[CTY == i & YEAR == 1, ID] %in%  dt[CTY == i & YEAR == j, ID] == T))
  }
}

加入后送什么

colnames(x) <- unique(dt$YEAR)
rownames(x) <- unique(dt$CTY)
x <- reshape2::melt(x)
names(x) <- c("CTY", "YEAR", "stayed")
x <- x[order(x$CTY),]

colnames(y) <- unique(dt$YEAR)
rownames(y) <- unique(dt$CTY)
y <- reshape2::melt(y)
names(y) <- c("CTY", "YEAR", "stayed2")
y <- y[order(y$CTY),]

dt <-dt[x, on = c("CTY", "YEAR")]
dt <-dt[y, on = c("CTY", "YEAR")]

dt

#     ID CTY YEAR stayed stayed2
#  1:  a   1    1     NA      NA
#  2:  b   1    1     NA      NA
#  3:  c   1    1     NA      NA
#  4:  d   1    1     NA      NA
#  5:  a   1    2      3       3
#  6:  c   1    2      3       3
#  7:  d   1    2      3       3
#  8:  e   1    2      3       3
#  9:  c   1    3      2       1
# 10:  e   1    3      2       1
# 11:  f   1    3      2       1
# 12:  a   2    1     NA      NA
# 13:  b   2    1     NA      NA
# 14:  c   2    1     NA      NA
# 15:  d   2    1     NA      NA
# 16:  a   2    2      3       3
# 17:  c   2    2      3       3
# 18:  d   2    2      3       3
# 19:  e   2    2      3       3
# 20:  c   2    3      2       1
# 21:  e   2    3      2       1
# 22:  f   2    3      2       1

这是正确的决赛桌,但它需要对循环输出进行操作,这似乎是不必要的;总而言之,这是可行的,但它笨重且缓慢。 我已经尝试过 data.table 和 dplyr 解决方案,但似乎无法成功。

【问题讨论】:

  • 根据你的循环代码没有得到预期的输出
  • 如果您能更详细地描述您正在尝试的计算,将会有所帮助。 stayed 的年留存率和stayed2 从一开始就一直存在吗?尽管您的输出仍处于ID 级别,但指标是在CTY:YEAR 级别计算的,对吗?也许您可以编辑您的示例数据,以便 stayed 的预期结果与 stayed2 不同 - 如果逻辑应该不同但结果应该相同,则更难以有效测试。跨度>
  • @GregorThomas 您的解释是正确的。刚刚编辑以更改 stay 和 stay2 的结果。
  • @AndreC 是正确的预期输出
  • @akrun 是正确的。我意识到措辞并不清楚。我会编辑。

标签: r dplyr data.table


【解决方案1】:

试试sapply这样的函数:

fx <- function(x) ifelse(x$YEAR == 1, NA, sum(dt[CTY == x$CTY & YEAR == x$YEAR, ID] %in%  dt[CTY == x$CTY & YEAR == x$YEAR-1, ID] == T))
fy <- function(y) ifelse(y$YEAR == 1, NA, sum(dt[CTY == y$CTY & YEAR == 1, ID] %in%  dt[CTY == y$CTY & YEAR == y$YEAR, ID] == T))

x <- merge(data.frame(CTY=1:2),data.frame(YEAR=1:3))
s <- data.frame(x,stayed=sapply(split(x,1:nrow(x)),fx))
s <- data.frame(s,stayed2=sapply(split(x,1:nrow(x)),fy))
    
merge(dt,s)

#     CTY YEAR ID stayed stayed2
#  1:   1    1  a     NA      NA
#  2:   1    1  b     NA      NA
#  3:   1    1  c     NA      NA
#  4:   1    1  d     NA      NA
#  5:   1    2  a      3       3
#  6:   1    2  c      3       3
#  7:   1    2  d      3       3
#  8:   1    2  e      3       3
#  9:   1    3  c      2       1
# 10:   1    3  e      2       1
# 11:   1    3  f      2       1
# 12:   2    1  a     NA      NA
# 13:   2    1  b     NA      NA
# 14:   2    1  c     NA      NA
# 15:   2    1  d     NA      NA
# 16:   2    2  a      3       3
# 17:   2    2  c      3       3
# 18:   2    2  d      3       3
# 19:   2    2  e      3       3
# 20:   2    3  c      2       1
# 21:   2    3  e      2       1
# 22:   2    3  f      2       1

【讨论】:

    猜你喜欢
    • 2020-01-09
    • 2020-04-13
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 2017-04-15
    相关资源
    最近更新 更多