如何用R

问题描述

我有一个数据帧,其中包含几个分散的NA值。我想在左边的单元格(相同的行)或紧随其后的单元格的右边(相同的行)的值填充那些NA,如果值不存在或为NA。似乎使用zoo::na.locftidyr::fill()可以解决此问题,但似乎只能通过在同一列中的上一个或下一个值取上一个/下一个值来起作用。

我目前有此代码,但它仅基于同一列中的上述值进行填充:

lapply(df,function(x) zoo::na.locf(zoo::na.locf(x,na.rm = FALSE),fromLast = TRUE))

我的数据框 df 如下:

  C1 C2 C3 C4
1  2  1  9  2
2 NA  5  1  1
3  1 NA  3  8
4  3 NA NA  4

structure(list(C1 = c(2,NA,1,3),C2 = c(1,5,NA),C3 = c(9,3,C4 = c(2,8,4)),row.names = c(NA,4L),class = "data.frame")

填写NA值后,我希望它看起来像这样:

  C1 C2 C3 C4
1  2  1  9  2
2  5  5  1  1
3  1  1  3  8
4  3  3  3  4

解决方法

这确实不是存储数据的常用方法,但是如果您只是转置,则可以使用tidyr::fill()。唯一的缺点是,它增加了很多包装代码。

xx <- structure(list(C1 = c(2,NA,1,3),C2 = c(1,5,NA),C3 = c(9,3,C4 = c(2,8,4)),row.names = c(NA,4L),class = "data.frame")


xx %>%
  t() %>%
  as_tibble() %>%
  tidyr::fill(everything(),.direction = "downup") %>%
  t() %>%
  as_tibble() %>%
  set_names(names(xx))
# A tibble: 4 x 4
#     C1    C2    C3    C4
#  <dbl> <dbl> <dbl> <dbl>
#1     2     1     9     2
#2     5     5     1     1
#3     1     1     3     8
#4     3     3     3     4
,

使用applyna.locf

library(zoo)
df[] <- t(apply(df,function(x) na.locf0(na.locf0(x),fromLast = TRUE)))

-输出

df
#   C1 C2 C3 C4
#1  2  1  9  2
#2  5  5  1  1
#3  1  1  3  8
#4  3  3  3  4
,

na.locf可以直接在数据框上运行,但可以按列运行。如果要使其按行运行,可以转置数据框。您也可以使用fromLast = TRUE从相反的方向填充数据。最后,我们使用coalesce从两个向量中选择第一个非NA值。

library(zoo)

df[] <- dplyr::coalesce(c(t(na.locf(t(df),na.rm = FALSE))),c(t(na.locf(t(df),na.rm = FALSE,fromLast = TRUE))))
df

#  C1 C2 C3 C4
#1  2  1  9  2
#2  5  5  1  1
#3  1  1  3  8
#4  3  3  3  4