如何解决 R 中响应变量的这种棘手的重新编码
How to tackle this tricky recoding of a response variable in R
我正在尝试重新编码一个在数据输入时编码不正确的变量。这(看起来)很棘手,我可以使用一些指导。
数据框(长格式)有三列:s_id(参与者标识符); i_id(项目标识符); 得分 (binary--0/1--correct/incorrect)。需要重新编码的是分数。
这个评估是这样的,对于每个参与者,项目被管理直到连续 6 个项目被错误回答(将第 6 个不正确的项目称为 基础 项目)。此时,另外管理了 14 个项目,并且 14 个之后的所有剩余项目都应该被编码为缺失。问题是 14 之后的所有项目都用零编码,这使得分析变得困难。
我需要一个新变量 n_score,通过循环每个参与者的原始分数创建,寻找六个连续 0 的第一个实例,然后再数 14 个.这些分数简单地放在 n_score 中,但每个参与者之后的分数应该重新编码 NA
。
我陷入了循环困境,需要一些帮助——也许是解决问题的聪明方法。下面是一个可重现的数据结构示例,其中添加了一个列 (n_score),这是新重新编码的变量的样子。
生成数据:
s_id <- rep(c(1:2), each = 25)
i_id <- rep(1:25, 2)
score <- c(1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,
1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1)
n_score <- c(1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,NA,NA,NA,
1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,NA,NA,NA)
dat <- data.frame(
s_id = s_id,
i_id = i_id,
score = score,
n_score = n_score
)
这是一个基于 R 的解决方案,将数据拆分 s_id
;在结果数据帧的 score
中寻找 6 个或更多零的运行;使用这些跑步结束的位置加上 14 将分数翻转为 NA
;然后将结果绑定到一个数据框中。
newdat <- do.call(rbind, lapply(split(dat, dat$s_id), function(i) {
x <- rle(i$score)
i$n_score <- ifelse(seq_along(i$score) > sum(x$lengths[1:which(x$lengths >= 6 & x$values == 0)]) + 14, NA, i$score)
return(i)
}))
结果:
> newdat
s_id i_id score n_score
1.1 1 1 1 1
1.2 1 2 1 1
1.3 1 3 0 0
1.4 1 4 0 0
1.5 1 5 0 0
1.6 1 6 0 0
1.7 1 7 0 0
1.8 1 8 0 0
1.9 1 9 1 1
1.10 1 10 0 0
1.11 1 11 1 1
1.12 1 12 0 0
1.13 1 13 0 0
1.14 1 14 0 0
1.15 1 15 1 1
1.16 1 16 1 1
1.17 1 17 0 0
1.18 1 18 0 0
1.19 1 19 1 1
1.20 1 20 0 0
1.21 1 21 0 0
1.22 1 22 0 0
1.23 1 23 1 NA
1.24 1 24 1 NA
1.25 1 25 1 NA
2.26 2 1 1 1
2.27 2 2 1 1
2.28 2 3 0 0
2.29 2 4 0 0
2.30 2 5 0 0
2.31 2 6 0 0
2.32 2 7 0 0
2.33 2 8 0 0
2.34 2 9 1 1
2.35 2 10 0 0
2.36 2 11 1 1
2.37 2 12 0 0
2.38 2 13 0 0
2.39 2 14 0 0
2.40 2 15 1 1
2.41 2 16 1 1
2.42 2 17 0 0
2.43 2 18 0 0
2.44 2 19 1 1
2.45 2 20 0 0
2.46 2 21 0 0
2.47 2 22 0 0
2.48 2 23 1 NA
2.49 2 24 1 NA
2.50 2 25 1 NA
我不知道这是否有效,但这是我的尝试:
dat$New_n_score <- NA
SixZeros <- rep(0, 6)
m <- length(SixZeros)
for(j in unique(dat$s_id)){
score <- dat$score[dat$s_id == j]
n <- length(score)
ind <- seq.int(length = n - m + 1)
pos <- rep(TRUE, times = n - m + 1)
for (i in seq.int(length = m)) {
pos <- pos & (SixZeros[i] == score[ind + i - 1])
}
n_score_stop <- which(pos) + 19
dat$New_n_score[dat$s_id == j][1:n_score_stop] <- dat$score[dat$s_id == j][1:n_score_stop]
}
此代码给出与 n_score 相同的输出:
mypattern = '000000'
recode <- function(x) {
start <- regexpr(mypattern, paste(x,collapse=''))
end <- start + 6 + 14 -1
return(c(x[1:end], rep(NA, length(x) - end)))
}
ddply(dat, .(s_id), transform, newcol=recode(score))
我正在尝试重新编码一个在数据输入时编码不正确的变量。这(看起来)很棘手,我可以使用一些指导。
数据框(长格式)有三列:s_id(参与者标识符); i_id(项目标识符); 得分 (binary--0/1--correct/incorrect)。需要重新编码的是分数。
这个评估是这样的,对于每个参与者,项目被管理直到连续 6 个项目被错误回答(将第 6 个不正确的项目称为 基础 项目)。此时,另外管理了 14 个项目,并且 14 个之后的所有剩余项目都应该被编码为缺失。问题是 14 之后的所有项目都用零编码,这使得分析变得困难。
我需要一个新变量 n_score,通过循环每个参与者的原始分数创建,寻找六个连续 0 的第一个实例,然后再数 14 个.这些分数简单地放在 n_score 中,但每个参与者之后的分数应该重新编码 NA
。
我陷入了循环困境,需要一些帮助——也许是解决问题的聪明方法。下面是一个可重现的数据结构示例,其中添加了一个列 (n_score),这是新重新编码的变量的样子。
生成数据:
s_id <- rep(c(1:2), each = 25)
i_id <- rep(1:25, 2)
score <- c(1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,
1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1)
n_score <- c(1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,NA,NA,NA,
1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,1,0,0,0,NA,NA,NA)
dat <- data.frame(
s_id = s_id,
i_id = i_id,
score = score,
n_score = n_score
)
这是一个基于 R 的解决方案,将数据拆分 s_id
;在结果数据帧的 score
中寻找 6 个或更多零的运行;使用这些跑步结束的位置加上 14 将分数翻转为 NA
;然后将结果绑定到一个数据框中。
newdat <- do.call(rbind, lapply(split(dat, dat$s_id), function(i) {
x <- rle(i$score)
i$n_score <- ifelse(seq_along(i$score) > sum(x$lengths[1:which(x$lengths >= 6 & x$values == 0)]) + 14, NA, i$score)
return(i)
}))
结果:
> newdat
s_id i_id score n_score
1.1 1 1 1 1
1.2 1 2 1 1
1.3 1 3 0 0
1.4 1 4 0 0
1.5 1 5 0 0
1.6 1 6 0 0
1.7 1 7 0 0
1.8 1 8 0 0
1.9 1 9 1 1
1.10 1 10 0 0
1.11 1 11 1 1
1.12 1 12 0 0
1.13 1 13 0 0
1.14 1 14 0 0
1.15 1 15 1 1
1.16 1 16 1 1
1.17 1 17 0 0
1.18 1 18 0 0
1.19 1 19 1 1
1.20 1 20 0 0
1.21 1 21 0 0
1.22 1 22 0 0
1.23 1 23 1 NA
1.24 1 24 1 NA
1.25 1 25 1 NA
2.26 2 1 1 1
2.27 2 2 1 1
2.28 2 3 0 0
2.29 2 4 0 0
2.30 2 5 0 0
2.31 2 6 0 0
2.32 2 7 0 0
2.33 2 8 0 0
2.34 2 9 1 1
2.35 2 10 0 0
2.36 2 11 1 1
2.37 2 12 0 0
2.38 2 13 0 0
2.39 2 14 0 0
2.40 2 15 1 1
2.41 2 16 1 1
2.42 2 17 0 0
2.43 2 18 0 0
2.44 2 19 1 1
2.45 2 20 0 0
2.46 2 21 0 0
2.47 2 22 0 0
2.48 2 23 1 NA
2.49 2 24 1 NA
2.50 2 25 1 NA
我不知道这是否有效,但这是我的尝试:
dat$New_n_score <- NA
SixZeros <- rep(0, 6)
m <- length(SixZeros)
for(j in unique(dat$s_id)){
score <- dat$score[dat$s_id == j]
n <- length(score)
ind <- seq.int(length = n - m + 1)
pos <- rep(TRUE, times = n - m + 1)
for (i in seq.int(length = m)) {
pos <- pos & (SixZeros[i] == score[ind + i - 1])
}
n_score_stop <- which(pos) + 19
dat$New_n_score[dat$s_id == j][1:n_score_stop] <- dat$score[dat$s_id == j][1:n_score_stop]
}
此代码给出与 n_score 相同的输出:
mypattern = '000000'
recode <- function(x) {
start <- regexpr(mypattern, paste(x,collapse=''))
end <- start + 6 + 14 -1
return(c(x[1:end], rep(NA, length(x) - end)))
}
ddply(dat, .(s_id), transform, newcol=recode(score))