我正在研究一个数据集,其中根据从临床记录中收集的数据计算得分。在某些情况下,此数据已被省略,因此无法计算分数并记录为 NA。
在某些情况下,我可以用以前的值替换 NA 值。这种方法的局限性是:
如果 score 为 NA,则检查上一个和下一个值是否为 NA。如果上一个和下一个值都不是 NA,则插入这些分数的平均值。
如果 score 为 NA,则检查上一个和下一个值是否为 NA。如果只有先前的值不是 NA,则用先前的值替换第一个 NA 值。
如果顺序有两个或多个 NA 值,则仅替换第一个 NA 值,其他值保留为 NA。
我已经尝试过函数 zoo::na.locf() 但这会不加选择地替换所有 NA 或限制替换比许多 NA 大的间隙。
我查看了 tidy fill 但文档中没有包含任何关于设置填充限制的内容。
对于以下数据:
ID,episode,score
1,1,1
1,2,1
1,3,1
1,4,NA
1,5,NA
1,6,NA
1,7,2
1,8,NA
1,9,4
1,10,NA
2,1,NA
2,2,2
2,3,3
2,4,4
2,5,NA
2,6,NA
2,7,3
2,8,NA
2,9,NA
2,10,NA
所以我认为我在下面嵌套的 ifelse mutate 上走在正确的轨道上,但我缺少有关可用于将替换限制为特定数量的 NA 值的函数的知识
data <- data %>%
group_by(ID) %>%
arrange(episode) %>%
mutate(score = ifelse(is.na(score) & lag(!is.na(score)) & lead(!is.na(score)), average(sum(lag(score),lead(score))),
ifelse(is.na(score) & lag(!is.na(score)) & lead(is.na(score)), lag(score), ...) #And this is where I get stuck as I am unsure how to code for NA runs greater than 1
我的预期输出是:
ID,episode,score
1,1,1
1,2,1
1,3,1
1,4,*1
1,5,NA
1,6,NA
1,7,2
1,8,*3
1,9,4
1,10,*4
2,1,NA
2,2,2
2,3,3
2,4,4
2,5,*4
2,6,NA
2,7,3
2,8,*3
2,9,NA
2,10,NA
添加 *s 以明确复制值的位置。
最佳答案
如果我理解正确,替换 NA
只有两条规则。列中的值 score
每个ID
:
NA
value 用前后(非 NA)值的平均值替换它。 NA
的序列值仅替换第一个 NA
值由前面的(非 NA)值并保留另一个 NA
值(value)观。 这两条规则的实现归结为两个简单的
mutate()
声明:一、全单
NA
根据规则 1 通过调用 zoo::na.approx()
替换值与 maxgap = 1L
.所以只有超过两个 NA
的序列值保留(如果有)。最后,每个NA
使用 if_else()
将值替换为前面的值和 lag()
为了满足规则 2。library(dplyr)
data %>%
group_by(ID) %>%
mutate(new_score = zoo::na.approx(score, x = row_number(), maxgap = 1, na.rm = FALSE)) %>%
mutate(new_score = if_else(is.na(new_score), lag(new_score), new_score))
# A tibble: 20 x 4 # Groups: ID [2] ID episode score new_score <dbl> <dbl> <dbl> <dbl> 1 1 1 1 1 2 1 2 1 1 3 1 3 1 1 4 1 4 NA 1 5 1 5 NA NA 6 1 6 NA NA 7 1 7 2 2 8 1 8 NA 3 9 1 9 4 4 10 1 10 NA 4 11 2 1 NA NA 12 2 2 2 2 13 2 3 3 3 14 2 4 4 4 15 2 5 NA 4 16 2 6 NA NA 17 2 7 3 3 18 2 8 NA 3 19 2 9 NA NA 20 2 10 NA NA
注意新列
new_score
创建是为了允许比较,这里。用于更换
score
用data %>%
group_by(ID) %>%
mutate(score = zoo::na.approx(score, x = row_number(), maxgap = 1, na.rm = FALSE)) %>%
mutate(score = if_else(is.na(score), lag(score), score))
数据
data <- readr::read_csv("ID,episode,score
1,1,1
1,2,1
1,3,1
1,4,NA
1,5,NA
1,6,NA
1,7,2
1,8,NA
1,9,4
1,10,NA
2,1,NA
2,2,2
2,3,3
2,4,4
2,5,NA
2,6,NA
2,7,3
2,8,NA
2,9,NA
2,10,NA")
关于根据特定规则替换 NA 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56404211/