由于这是我第一次在SO上提问,我提前为任何不正确的格式化道歉。
我是R的新手,我正在尝试创建一个函数,一旦另一列中的运行总计达到或超过给定值(运行总和开始的行),它将返回数据框列的行值也是一个论点。
例如,给定以下数据框,如果给定起始参数x = 3且停止参数y = 17,则该函数应返回5(行的x值,其中y>的总和= 17 )。
X Y
1 5
2 10
3 5
4 10
5 5
6 10
7 5
8 10
我目前编写的函数返回正确的答案,但我必须相信有更多的“R-ish”方法来实现这一点,而不是使用循环和递增临时变量,并希望学会正确的方法,而不是形成我以后必须纠正的坏习惯。
该功能的一个非常简化的版本:
myFunction<-function(DataFrame,StartRow,Total){
df<-DataFrame[DataFrame[[1]] >= StartRow,]
i<-0
j<-0
while (j < Total) {
i<-i+1
j<-sum(df[[2]][1:i])
}
x<-df[[1]][i]
return(x)
}
答案 0 :(得分:4)
到目前为止发布的所有解决方案都计算整个Y
变量的累积和,在数据帧非常大但索引接近开头的情况下,这可能是低效的。在这种情况下,使用Rcpp的解决方案可能更有效:
library(Rcpp)
get_min_cum2 = cppFunction("
int gmc2(NumericVector X, NumericVector Y, int start, int total) {
double running = 0.0;
for (int idx=0; idx < Y.size(); ++idx) {
if (X[idx] >= start) {
running += Y[idx];
if (running >= total) {
return X[idx];
}
}
}
return -1; // Running total never exceeds limit
}")
与microbenchmark的比较:
get_min_cum <-
function(start,total)
with(dat[dat$X>=start,],X[min(which(cumsum(Y)>total))])
get_min_dt <- function(start, total)
dt[X >= start, X[cumsum(Y) >= total][1]]
set.seed(144)
dat = data.frame(X=1:1000000, Y=abs(rnorm(1000000)))
dt = data.table(dat)
get_min_cum(3, 17)
# [1] 29
get_min_dt(3, 17)
# [1] 29
get_min_cum2(dat$X, dat$Y, 3, 17)
# [1] 29
library(microbenchmark)
microbenchmark(get_min_cum(3, 17), get_min_dt(3, 17),
get_min_cum2(dat$X, dat$Y, 3, 17))
# Unit: milliseconds
# expr min lq median uq max neval
# get_min_cum(3, 17) 125.324976 170.052885 180.72279 193.986953 418.9554 100
# get_min_dt(3, 17) 100.990098 149.593250 162.24523 176.661079 399.7531 100
# get_min_cum2(dat$X, dat$Y, 3, 17) 1.157059 1.646184 2.30323 4.628371 256.2487 100
在这种情况下,使用Rcpp解决方案比其他方法快约100倍。
答案 1 :(得分:1)
试试这个例子,我正在使用cumsum
和矢量化逻辑子集:
get_min_cum <-
function(start,total)
with(dat[dat$X>=start,],X[min(which(cumsum(Y)>total))])
get_min_cum(3,17)
5
答案 2 :(得分:1)
在这里(由于语法简单,使用data.table
):
library(data.table)
dt = data.table(df)
dt[X >= 3, X[cumsum(Y) >= 17][1]]
#[1] 5
答案 3 :(得分:1)
嗯,这是一种方式:
i <- 3
j <- 17
min(df[i:nrow(df),]$X[cumsum(df$Y[i:nrow(df)])>j])
# [1] 5
对df$X
行i:nrow(df)
和基于cumsum(df$Y) > j
的索引,从第i行开始。这将返回df$X
的所有cumsum > j
。 min(...)
然后返回最小值。
答案 4 :(得分:1)
with(df, which( cumsum( (x>=3)*y) >= 17)[1] )