用序列中的缺失值替换 NA (R)
Posted
技术标签:
【中文标题】用序列中的缺失值替换 NA (R)【英文标题】:Replace NAs with missing values in sequence (R) 【发布时间】:2021-10-11 00:05:53 【问题描述】:我有一个像这样的DF
现在我想将 Col B = NA 替换为 15,因为这是缺失值。 Col C 第一个 NA 为 14,第二个 NA 为 15。 Col D 第一个 NA 为 13,第二个 NA 为 14,第三个 NA 为 15。 所以数字遵循从上到下或从下到上的顺序。
可重现的样本数据
structure(list(`Col A` = c(11, 12, 13, 14, 15), `Col B` = c(NA,
11, 12, 13, 14), `Col C` = c(NA, NA, 11, 12, 13), `Col D` = c(NA,
NA, NA, 11, 12)), row.names = c(NA, -5L), class = c("tbl_df",
"tbl", "data.frame"))
【问题讨论】:
【参考方案1】:我认为您可以在tidyverse
中使用以下解决方案:
library(dplyr)
library(purrr)
df[1] %>%
bind_cols(map_dfc(2:length(df), function(x)
df[[x]][which(is.na(df[[x]]))] <- setdiff(df[[1]], df[[x]][!is.na(df[[x]])])
df[x]
))
# A tibble: 5 x 4
`Col A` `Col B` `Col C` `Col D`
<dbl> <dbl> <dbl> <dbl>
1 11 15 14 13
2 12 11 15 14
3 13 12 11 15
4 14 13 12 11
5 15 14 13 12
或者在 base R 中我们可以这样做:
do.call(cbind, Reduce(function(x, y)
i <- which(is.na(df[[y]]))
df[[y]][i] <- sort(setdiff(x, df[[y]]))
df[[y]]
, init = df[[1]], 2:length(df), accumulate = TRUE)) |>
as.data.frame() |>
setNames(paste0("Col", LETTERS[1:length(df)]))
ColA ColB ColC ColD
1 11 15 14 13
2 12 11 15 14
3 13 12 11 15
4 14 13 12 11
5 15 14 13 12
【讨论】:
绝妙的答案!亲爱的朋友【参考方案2】:你可以试试:
df[is.na(df)] <- head(tm <- toeplitz(rev(df$ColA))[upper.tri(tm, diag = TRUE)], sum(is.na(df)))
这给出了:
ColA ColB ColC ColD
1 11 15 14 13
2 12 11 15 14
3 13 12 11 15
4 14 13 12 11
5 15 14 13 12
【讨论】:
【参考方案3】:试试下面的代码
df[-1] <- lapply(
df[-1],
function(x)
replace(x, is.na(x), df[[1]][is.na(match(df[[1]], x))])
)
你会得到
> df
# A tibble: 5 x 4
`Col A` `Col B` `Col C` `Col D`
<dbl> <dbl> <dbl> <dbl>
1 11 15 14 13
2 12 11 15 14
3 13 12 11 15
4 14 13 12 11
5 15 14 13 12
【讨论】:
真正优雅简洁。【参考方案4】:如果序列是恒定的(在这种情况下从 11 到 15),那么使用 dplyr
的一个选项可能是:
df %>%
mutate(across(everything(), ~ if_else(is.na(.), max(., na.rm = TRUE) + cumsum(is.na(.)), .)))
`Col A` `Col B` `Col C` `Col D`
<dbl> <dbl> <dbl> <dbl>
1 11 15 14 13
2 12 11 15 14
3 13 12 11 15
4 14 13 12 11
5 15 14 13 12
如果顺序可能不同,那么一种选择可能是:
df %>%
mutate(across(-1,
~ if_else(is.na(.),
cumsum(is.na(.)) - 1 + last(pull(select(cur_data(), which(names(cur_data()) == cur_column()) - 1))),
.)))
或者:
df %>%
mutate(across(-1,
~ if_else(is.na(.),
cumsum(is.na(.)) - 1 + last(get(paste0("Col ", LETTERS[which(names(cur_data()) == cur_column()) - 1]))),
.)))
【讨论】:
以上是关于用序列中的缺失值替换 NA (R)的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用isna函数查看列表和dataframe中是否包含缺失值将dataframe中数据列中的异常值标注为缺失值NA使用na.omit函数删除dataframe中包含缺失值NA的数据行