[英]How to use the same function on different intervals of a vector in R without loops or mapply?
假設我有一個數據框,如
Date Value
1 2014-04-14 830.61
2 2014-04-11 815.69
3 2014-04-10 833.08
4 2014-04-09 872.18
5 2014-04-08 851.96
6 2014-04-07 845.04
7 2014-04-04 865.09
8 2014-04-03 888.77
9 2014-04-02 890.90
10 2014-04-01 885.52
我們把它命名為DF。 假設我已經定義了索引號的最小值和最大值。
minvals<-c(1,2,3)
maxvals<-c(5,7,10)
我想為每個區間處理一個函數(即值列的平均值或標准差)。 例如,取第一個間隔的平均值。
DF[minvals[1]:maxvals[1],"Value"]
Date Value
1 2014-04-14 830.61
2 2014-04-11 815.69
3 2014-04-10 833.08
4 2014-04-09 872.18
5 2014-04-08 851.96
mean(DF[minvals[1]:maxvals[1],"Value"])
#840.704
也適用於其他小型和小型。 首先想到的是mapply。 但是因為我的數據包含了數千個這樣的小數和最大值。 是否有可能以有效的方式做到這一點?
ps實際上,它與滾動平均值非常相似,但我的日期列僅包括工作日,因此我不確定zoo包的rollmean函數是否可以處理這個問題。 無論如何,假設我的時間間隔也不規律。
試試data.table
DFvec <- DF$Value
Ints <- data.frame(MIN = c(1,2,3), MAX = c(5,7,10))
library(data.table)
setDT(Ints)[, MEAN := mean(DFvec[MIN:MAX]), by = c("MIN", "MAX")]
Ints
## MIN MAX MEAN
## 1: 1 5 840.7040
## 2: 2 7 847.1733
## 3: 3 10 866.5675
其他方式:
minvals = as.integer(minvals)
maxvals = as.integer(maxvals)
lenvals = maxvals - minvals + 1L
ix = data.table:::vecseq(minvals, lenvals, sum(lenvals))
grp = rep(seq_along(lenvals), lenvals)
setDT(DF[ix, ])[, list(Value=mean(Value)), by=grp]
# grp Value
# 1: 1 840.7040
# 2: 2 847.1733
# 3: 3 866.5675
這是mapply
解決方案。 如果這太慢了(給出一個可重現的問題大小示例),你可以用data.table做一些聰明的事情或使用Rcpp。
x <- DF[["Value"]] #avoid data.frame subsetting in a loop
mapply(function(i1, i2) mean.default(x[i1:i2]), minvals, maxvals)
1e5間隔的基准:
library(microbenchmark)
set.seed(42)
i <- sample(1:3, 1e5, TRUE)
minvals<-c(1,2,3)[i]
maxvals<-c(5,7,10)[i]
microbenchmark(mapply(function(i1, i2) mean.default(x[i1:i2]), minvals, maxvals), times=10)
Unit: milliseconds
expr min lq median uq max neval
mapply(function(i1, i2) mean.default(x[i1:i2]), minvals, maxvals) 446.0529 473.4267 489.2375 523.2335 595.5536 10
這是幾種方法。 從描述中不清楚效率在這里真的很重要,可讀性可能更重要:
# they all use this:
DF.Value <- DF$Value
# 1
sapply(seq_along(minvals), function(i) mean(DF.Value[minvals[i]:maxvals[i]]))
# 2
f <- function(minvals, maxvals) mean(DF.Value[minvals:maxvals])
mapply(f, minvals, maxvals)
# 3 - this one assumes that minvals equals seq_along(minvals) which is true in example
library(zoo)
w <- maxvals - minvals + 1
rollapply(DF.Value, w, mean, align = "left")[minvals]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.