R:在第一个非零之后计算所有值的方差

R: Calculate Variance on all Values after the first Non-Zero

这是较早问题的后续问题:,但下面对问题进行了完整解释。

我有一个这样的数据框:

Data <- data.frame(ID = 1:4, Value1=c(0,12,0,0), Value2=c(12,0,10,0), Value3=c(21,0,0,8), Value4=c(18,5,17,29))

ID  Value1  Value2  Value3  Value4
1   0       12      21      18               
2   12      0       0       5
3   0       10      0       17
4   0       0       8       29

我想做的是根据行中的每个值(包括第一个非零值和第一个非零值之后)计算每个人 (ID) 的方差。

例如,在此示例中,ID 1 的方差为 var(c(12, 21, 18)), 对于 ID 2,它将 var(c(12, 0, 0, 5)),对于 ID 3,var 将是 var(c(10, 0, 17)),对于 ID 4,它将是 var(c(8, 29)).

我该怎么做?我目前有以下代码,它删除所有零,而不是只删除非零值之前的那些:

varfunc <- function(x) var(x[x > 0])
variances = apply(d[,c(-1)], 1, varfunc)

我想不出办法来避免apply这里,但这里有一个可能的解决方案

varfunc <- function(x) var(x[which(x != 0)[1L]:length(x)])
apply(d[-1], 1, varfunc)
## [1]  21.00  32.25  73.00 220.50

基本上我们用第一个非零值对每一行进行子集 - 直到列数并计算方差。

我们可以根据您的规则轻松验证结果

var(c(12, 21, 18))
## [1] 21
var(c(12, 0, 0, 5))
## [1] 32.25
var(c(10, 0, 17))
## [1] 73
var(c(8, 29))
## [1] 220.5

逐行应用方差函数(使用apply,第一个边距是行);方差函数应该通过取第一个值 which() 不是 0 和所有后续值(which(x!=0)[1]:length(x) 提供用于子集的索引)来对行中的值进行子集化。

这是您的解决方案:

Data <- data.frame(ID = 1:5, Value1=c(0,12,0,0,0), Value2=c(12,0,10,0,0), Value3=c(21,0,0,8,0), Value4=c(18,5,17,29,0))

var.after0 <- function(x){
    x.vals <- as.numeric(x[-1]) # need to convert b/c x can be a data.frame, not just matrix
    if(all(x.vals==0)){
        return(0) # just return a 0 here so we don't create an empty subset later
    }else{
        n.vals <- length(x.vals) # how many values?
        x.vals.not0 <- which(x.vals!=0) # positions (indices) of values that are not 0
        first.not0 <- x.vals.not0[1] # the position of the first non-0 value
        x.vals.after0 <- x.vals[first.not0:n.vals] # the non-0 values after first 0
        var(x.vals.after0) # variance of the non-0 values after first 0
    }
}

apply(Data, 1, var.after0)

哪个returns:

[1]  21.00  32.25  73.00 220.50   0.00

注意:我在您的数据集中添加了一个额外的行,其中包含全 0。这是一个重要的情况,方差函数应该能够处理以便稳健。以为这样的调整会派上用场。如果您同意,请随时将其复制到您的原始问题中。