Rのグループごとの年間保持率を計算する方法は?

Nov 21 2020

私は、数年にわたって郡にいる個人の大規模なデータセットを持っています。毎年、一部の個人は別の郡に移動するか、データセットを離れて新しい個人が参加します。毎年、1年目から同じ郡に滞在した個人の数を数えたいと思います。このタスクに最も近いとわかった質問は次のとおりです(郡による追加のグループ化なし):月ごと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ソリューションを試しましたが、機能しないようです。

回答

MarcosPérez Nov 23 2020 at 21:21

次の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