用序列中的缺失值替换 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语言把dataframe中的NA值替换为0

如何用相邻值替换数据框中的 NA(缺失值)

R语言使用isna函数查看列表和dataframe中是否包含缺失值将dataframe中数据列中的异常值标注为缺失值NA使用na.omit函数删除dataframe中包含缺失值NA的数据行

R语言自定义函数计算dataframe每列中的缺失值NA的个数缺失值问题及其填充示例

用计算值替换缺失值

r从缺失值以上的单元格中复制值[重复]