我正在尝试使用以下语法将一个向量复制到另一个向量:
data<-NULL
for( i in 1:nrow(line)){
data=append(data,line[i*4])
}
从我所看到的情况来看,以这种方式使用append
会导致大量数据复制,这使得R非常慢。将一个数组的第四个元素复制到另一个数组的语法是什么,假设您复制的列表具有给定的大小?
答案 0 :(得分:2)
如果您尝试从向量中提取每个第四个元素,则可以使用seq
进行索引以获取正确的元素:
data <- letters[seq(4, length(letters), by=4)]
data
# [1] "d" "h" "l" "p" "t" "x"
当您在问题中显示时,一次增长一个向量将会很慢,因为您需要不断重新分配向量(有关详细信息,请参阅The R Inferno的第二个圆圈)。但是,与在单个矢量化索引操作中构造向量相比,即使预先分配向量并使用for循环构造它也会很慢。
要了解速度的提升,请考虑与您所描述的方法进行比较,除非使用预分配:
for.prealloc <- function(x) {
data <- vector(mode="numeric", length = floor(length(x)/4))
for (i in 1:floor(length(x)/4)) {
data[i] <- x[i*4]
}
data
}
josilber <- function(x) x[seq(4, length(x), by=4)]
r <- rnorm(10000)
all.equal(for.prealloc(r), josilber(r))
# [1] TRUE
library(microbenchmark)
microbenchmark(for.prealloc(r), josilber(r))
# Unit: microseconds
# expr min lq mean median uq max neval
# for.prealloc(r) 1846.014 2035.7890 2351.9681 2094.804 2244.56 5283.285 100
# josilber(r) 95.757 97.4125 125.9877 113.179 138.96 259.606 100
我建议的方法比使用for
和预先分配的向量快20倍(它甚至比使用append
和非预先分配的向量更快。)
答案 1 :(得分:2)
以下是基准测试的三种方法。你可以看到在method2
函数中预先分配向量的速度要快得多,而lapply方法是中等的,而你的函数是最慢的。
当然,这些是1D向量而不是n-D阵列,但我预计基准测试会相似甚至更加明显。
method1 <- function(line) {
data<-NULL
for( i in 1:length(line)){
data=append(data,line[i])
}
}
method2 <- function(line) {
data <- vector(mode="numeric", length = length(line))
for (i in 1:length(line)) {
data[i] <- line[i]
}
}
library(microbenchmark)
r <- rnorm(1000)
microbenchmark(method2(r), unit="ms")
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> method2(r) 2.18085 2.279676 2.428731 2.371593 2.500495 5.24888 100
microbenchmark(lapply(r, function(x) { data<-append(data, x) }), unit="ms")
#> Unit: milliseconds
#> expr min lq
#> lapply(r, function(x) { data <- append(data, x) }) 3.014673 3.091299
#> mean median uq max neval
#> 3.287216 3.150052 3.260199 6.036501 100
microbenchmark(method1(r), unit="ms")
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> method1(r) 3.938684 3.978002 5.71831 4.020001 4.280521 98.58584 100
没有意识到OP只想要每四分之一。为什么不使用数据框或data.table?
d <- data.frame(matrix(rnorm(1000), ncol=1))
microbenchmark(d2 <- d[seq(1,nrow(d), 4),])
#> Unit: microseconds
#> expr min lq mean median uq
#> d2 <- d[seq(1, nrow(d), 4), ] 64.846 65.9915 73.08007 67.225 73.8225
#> max neval
#> 220.438 100
library(data.table)
dt <- data.table(d)
microbenchmark(d2 <- dt[seq(1,nrow(d), 4),])
#> Unit: microseconds
#> expr min lq mean median uq
#> d2 <- dt[seq(1, nrow(d), 4), ] 298.163 315.2025 324.8793 320.554 330.416
#> max neval
#> 655.124 100