4

条件が含まれているデータ フレーム内の列のローリング行合計を計算する必要があります。私が持っているデータには、「sku」の複数の観測があります。私が望むのは、「sku」の値ごとに連続する 5 行の合計を計算することです。「sku」の 5 つの連続した観察がない段階に達した場合、そのそれぞれの値の残りの行の観察を合計します。

実例として、次のデータ フレームを考えてみましょう。

data <- structure(list(sku = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
                           2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
                           3L, 3L, 3L, 3L), tf = c(50.79, 46.39, 47.85, 45.79, 44.46, 49.99, 
                                                   46.12, 44.4, 41.21, 53.7, 53.9, 44.91, 59.64, 41.96, 52.26, 43.48, 
                                                   46.93, 51.2, 54.31, 42.5, 47.2, 57.54, 63.23, 48.98, 52.38, 59.9, 
                                                   53.01, 50.35, 41.86, 46.42)), .Names = c("sku", "tf"), row.names = c(NA, 
                                                  -30L), class = "data.frame")

このデータフレームでは、各「sku」値の 5 つのローリング値の変数「tf」を合計します。

次のコードを使用してそれを達成できました。

data[,c("day_5")]<-unlist(mapply(function(y){
end1<-(which(data$sku==unique(data$sku)[y]))[length(which(data$sku==unique(data$sku)[y]))]  
start<-(which(data$sku==unique(data$sku)[y]))[1]
d<-data$tf[start:end1]
r<-mapply(function(x){if (x+4 <= length(d)) {sum(d[x:(x+4)])} else {sum(d[x:length(d)])}},1:length(d))
},1:length(unique(data$sku))))

列「day_5」はまさに私たちが望むものを提供しますが、「sku」の数千の値を持つ数百万行のデータに対してこの操作を実行する必要があるため、この方法は非常に非効率的であることが判明しました。

このコードを大規模なデータにスケールアップできる方法で最適化するのを手伝ってくれる人はいますか?

4

3 に答える 3

4

巨大なデータセットでは、パッケージ data.table を使用する必要があります。パッケージzooは、ローリング平均、合計、および適用のための機能を提供します。

library(data.table)
DT <- data.table(data)

library(zoo)
fun <- function(x, i) {
  x <- c(x, rep(0, i-1))
  rollsumr(x, k=i)
}

DT[, day_5a:=fun(tf,5), by=sku]
print(DT)

#     sku    tf  day_5 day_5a
# 1:    1 50.79 235.28 235.28
# 2:    1 46.39 234.48 234.48
# 3:    1 47.85 234.21 234.21
# 4:    1 45.79 230.76 230.76
# 5:    1 44.46 226.18 226.18
# 6:    1 49.99 181.72 181.72
# 7:    1 46.12 131.73 131.73
# 8:    1 44.40  85.61  85.61
# 9:    1 41.21  41.21  41.21
# 10:   2 53.70 254.11 254.11
# 11:   2 53.90 252.67 252.67
#<snip>
于 2013-10-30T15:38:29.610 に答える
1

Ronald から関数を借りて、より簡単な方法は次を使用することです。

fun <- function(x, i) {
  x <- c(x, rep(0, i-1))
  rollsumr(x, k=i)
}
data$day_5_a <- ave(data$tf, data$sku, FUN= function(x) fun(x, 5))
于 2013-10-30T15:58:02.173 に答える
1

のみを使用するbase明らかに効率が低く、エレガントではありませんdata.table):

data_ls <- split(data, data$sku)

res <- lapply(data_ls, 
           function(z) sapply(1:length(z$tf), 
               function(vec, x) { sum(vec[x:(x+4)], na.rm = T) }, 
                 vec = z$tf))

data$day_5 <- unlist(res)

#> data
#   sku    tf  day_5
#1    1 50.79 235.28
#2    1 46.39 234.48
#3    1 47.85 234.21
#4    1 45.79 230.76
#5    1 44.46 226.18
#6    1 49.99 181.72
#7    1 46.12 131.73
#8    1 44.40  85.61
#9    1 41.21  41.21
#10   2 53.70 254.11
#11   2 53.90 252.67
#12   2 44.91 242.25
于 2013-10-30T16:02:24.893 に答える