我有一个数字向量:
x <- c(0, 0, 0, 30, 60, 0, 0, 0, 0, 0, 10, 0, 0, 15, 45, 0, 0)
对于i
中的每个元素x
,我想执行以下操作
x[i] > 0
,则返回0 x[i]
之前的所有4个元素都是0
,则返回NA x[i]
之前的4个元素不是0
,请计算最后一个元素 - 0
元素与x[i]
我期待这个输出:
#> x
#[1] 0 0 0 30 60 0 0 0 0 0 10 0 0 15 45 0 0
#> x_out
#[1] NA NA NA 0 0 1 2 3 4 NA 0 1 2 0 0 1 2
请注意,当向量的开头有少于4个元素时,解决方案也应该起作用(即条件2和3应该使用尽可能多的元素)。有人有解决方案吗?首选矢量化方法,因为矢量很长,数据集相当大。
答案 0 :(得分:3)
这是一个简单的Rcpp解决方案。在RStudio中创建一个新的C ++文件并将代码粘贴到其中并获取文件。显然,如果您使用Windows,则需要安装Rtools。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector funRcpp(const IntegerVector x) {
const double n = x.length();
int counter = 4;
IntegerVector y(n);
for (double i = 0; i < n; ++i) {
if (x(i) > 0) {
y(i) = 0;
counter = 0;
}
else {
if (counter > 3) {
y(i) = NA_INTEGER;
} else {
counter++;
y(i) = counter;
}
}
}
return y;
}
/*** R
x <- c(0, 0, 0, 30, 60, 0, 0, 0, 0, 0, 10, 0, 0, 15, 45, 0, 0)
funRcpp(x)
*/
这将返回所需的结果:
> funRcpp(x)
[1] NA NA NA 0 0 1 2 3 4 NA 0 1 2 0 0 1 2
答案 1 :(得分:0)
这是我目前的做法:
library(dplyr)
last_x_months <- 4
my_list <- vector("list", 1 + last_x_months)
my_list[[1]] <- x
# create lagged variants of vector
for (j in seq_along(1:last_x_months)) {
my_list[[1 + j]] <- lag(my_list[[1]], n = j, default = NA)
}
# row bind it to a data.frame
i_dat <- do.call(rbind, my_list) %>%
as.data.frame()
# apply function to each column in dataframe
sapply(i_dat, function(x) {
if (sum(x, na.rm = TRUE) == 0) {
NA
} else if (x[1] > 0) {
0
} else {
rle(x)$lengths[1]
}
})
这是我得到的输出:
#> output
#[1] NA NA NA 0 0 1 2 3 4 NA 0 1 2 0 0 1 2
这是一种好的做法,还是可以通过快捷方式提高性能?在性能优化方面我很缺乏经验,这就是我提出这个问题的原因。