我正在尝试使用以下数据集将NA
值重新编码0
为列的子集:
set.seed(1)
df <- data.frame(
id = c(1:10),
trials = sample(1:3, 10, replace = T),
t1 = c(sample(c(1:9, NA), 10)),
t2 = c(sample(c(1:7, rep(NA, 3)), 10)),
t3 = c(sample(c(1:5, rep(NA, 5)), 10))
)
每行都有与之相关的一定次数的试验(在1-3之间),由trials
列指定。列t1-t3
代表每个试验的分数。
试用次数表示NA
应将s编码为的列的子集0
:NA
在试用次数之内的s表示缺少数据,应将其重新编码为0
,而NA
在试用次数之外的s没有意义,应保留NA
s 。因此,对于其中的行trials == 3
,NA
in列t3
将被重新编码为0
,但是对于其中的行trials == 2
,NA
int3
将保留为NA
。
因此,我尝试使用此功能:
replace0 <- function(x, num.sun) {
x[which(is.na(x[1:(num.sun + 2)]))] <- 0
return(x)
}
这对于单个向量效果很好。当我尝试使用将相同的功能应用于数据框时apply()
:
apply(df, 1, replace0, num.sun = df$trials)
我收到警告说:
In 1:(num.sun + 2) :
numerical expression has 10 elements: only the first used
结果是,与其根据中的值来num.sun
改变每一行的值trials
,apply()
不如trials
对每一行使用列中的第一个值。我如何应用该函数,以使num.sun
参数根据的值而变化df$trials
?
谢谢!
编辑:正如一些评论所述,原始示例数据具有一些非NA得分,根据试验列,这些得分没有意义。这是一个更正的数据集:
df <- data.frame(
id = c(1:5),
trials = c(rep(1, 2), rep(2, 1), rep(3, 2)),
t1 = c(NA, 7, NA, 6, NA),
t2 = c(NA, NA, 3, 7, 12),
t3 = c(NA, NA, NA, 4, NA)
)
另一种方法:
# create an index of the NA values
w <- which(is.na(df), arr.ind = TRUE)
# create an index with the max column by row where an NA is allowed to be replaced by a zero
m <- matrix(c(1:nrow(df), (df$trials + 2)), ncol = 2)
# subset 'w' such that only the NA's which fall in the scope of 'm' remain
i <- w[w[,2] <= m[,2][match(w[,1], m[,1])],]
# use 'i' to replace the allowed NA's with a zero
df[i] <- 0
这使:
> df id trials t1 t2 t3 1 1 1 3 NA 5 2 2 2 2 2 NA 3 3 2 6 6 4 4 4 3 0 1 2 5 5 1 5 NA NA 6 6 3 7 0 0 7 7 3 8 7 0 8 8 2 4 5 1 9 9 2 1 3 NA 10 10 1 9 4 3
您可以轻松地将其包装在一个函数中:
replace.NA.with.0 <- function(df) {
w <- which(is.na(df), arr.ind = TRUE)
m <- matrix(c(1:nrow(df), (df$trials + 2)), ncol = 2)
i <- w[w[,2] <= m[,2][match(w[,1], m[,1])],]
df[i] <- 0
return(df)
}
现在,使用replace.NA.with.0(df)
将产生以上结果。
正如其他人所指出的,某些行(1、3和10)的值比尾数更多。您可以通过将上面的函数重写为以下方法来解决该问题:
replace.with.NA.or.0 <- function(df) {
w <- which(is.na(df), arr.ind = TRUE)
df[w] <- 0
v <- tapply(m[,2], m[,1], FUN = function(x) tail(x:5,-1))
ina <- matrix(as.integer(unlist(stack(v)[2:1])), ncol = 2)
df[ina] <- NA
return(df)
}
现在,使用replace.with.NA.or.0(df)
产生以下结果:
id trials t1 t2 t3 1 1 1 3 NA NA 2 2 2 2 2 NA 3 3 2 6 6 NA 4 4 3 0 1 2 5 5 1 5 NA NA 6 6 3 7 0 0 7 7 3 8 7 0 8 8 2 4 5 NA 9 9 2 1 3 NA 10 10 1 9 NA NA
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句