这是前一个问题的后续问题:R: Find the Variance of all Non-Zero Elements in Each Row,但问题将在下面详细解释。
我有一个像这样的数据框:
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)
答案 0 :(得分:3)
我想不出办法来避免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
答案 1 :(得分:3)
逐行应用方差函数(使用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)
返回:
[1] 21.00 32.25 73.00 220.50 0.00
注意:我在数据集中添加了一行,其中包含全部0。这是方差函数应该能够处理以便稳健的重要情况。认为这样的调整会派上用场。如果您同意,请随意将其复制到原始问题中。