根据因子水平填充缺失的 NA

Filling in missing NA based upon factor level

我一直在尝试将我的数据从垂直配置转换为水平配置。使用 spread(),我设法得到了以下结构:

plot, x1, x2, x3, x4, x5, x6, x7
1   0.06011071  NA  NA  NA  NA  NA  NA
1   NA  0.09756118  NA  NA  NA  NA  NA
1   NA  NA  NA  NA  0.143701    NA  NA
1   NA  NA  NA  NA  NA  0.1584451   NA
1   NA  NA  NA  0.1809486   NA  NA  NA
1   NA  NA  NA  NA  NA  NA  0.1151581
1   NA  NA  -0.1422974  NA  NA  NA  NA
7 rows

但是,显然我想用其他行的信息填充 NA。然后我的数据看起来像

plot , x1, x2, x3, x4, x5, x6, x7
1   0.06011071  0.09756118  -0.1422974NA    0.1809486   0.143701     0.1584451      0.1151581

我尝试了多种方法,但到目前为止都没有成功。有谁知道我怎样才能做到这一点?

是这样的吗?

df <- data.frame(x1 = c(1,NA,NA,NA,NA),
                 x2 = c(NA,2,NA,NA,NA),
                 x3 = c(NA,NA,3,NA,NA),
                 x4 = c(NA,NA,NA,4,NA),
                 x5 = c(NA,NA,NA,NA,5))
> df
  x1 x2 x3 x4 x5
1  1 NA NA NA NA
2 NA  2 NA NA NA
3 NA NA  3 NA NA
4 NA NA NA  4 NA
5 NA NA NA NA  5

for (i in 1:ncol(df)){
  df[,i][is.na(df[,i])] <- df[,i][!is.na(df[,i])]
}

> df
  x1 x2 x3 x4 x5
1  1  2  3  4  5
2  1  2  3  4  5
3  1  2  3  4  5
4  1  2  3  4  5
5  1  2  3  4  5

这是使用 dplyr 的解决方案。它假定您希望为每个 plot.

保留顶部的第一个非 NA 值
library(dplyr)

dat2 <- dat %>%
  group_by(plot) %>%
  summarize(
    across(
      everything(),
      .fns = ~first(.x[!is.na(.x)])
    )
  ) %>%
  ungroup()
dat2
# # A tibble: 1 x 8
#    plot     x1     x2     x3    x4    x5    x6    x7
#   <int>  <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     1 0.0601 0.0976 -0.142 0.181 0.144 0.158 0.115

数据

dat <- read.table(text = "plot  x1  x2  x3  x4  x5  x6  x7
1   0.06011071  NA  NA  NA  NA  NA  NA
1   NA  0.09756118  NA  NA  NA  NA  NA
1   NA  NA  NA  NA  0.143701    NA  NA
1   NA  NA  NA  NA  NA  0.1584451   NA
1   NA  NA  NA  0.1809486   NA  NA  NA
1   NA  NA  NA  NA  NA  NA  0.1151581
1   NA  NA  -0.1422974  NA  NA  NA  NA",
                  header = TRUE)

或者:

library(tidyverse)

d <- read.table(text = "plot, x1, x2, x3, x4, x5, x6, x7
1   0.06011071  NA  NA  NA  NA  NA  NA
1   NA  0.09756118  NA  NA  NA  NA  NA
1   NA  NA  NA  NA  0.143701    NA  NA
1   NA  NA  NA  NA  NA  0.1584451   NA
1   NA  NA  NA  0.1809486   NA  NA  NA
1   NA  NA  NA  NA  NA  NA  0.1151581
1   NA  NA  -0.1422974  NA  NA  NA  NA", header = TRUE)

d %>%
  summarise(across(starts_with("x"), sum, na.rm = TRUE))

#x1.        x2.        x3.       x4.      x5.       x6.        x7
#1 0.06011071 0.09756118 -0.1422974 0.1809486 0.143701 0.1584451 0.1151581

我们也可以将na.omit与dplyr一起使用:

df %>% group_by(plot) %>% summarise(across(matches('x\d+'), na.omit))

也许:

library(tidyverse)

df <- read.table(text = "plot, x1, x2, x3, x4, x5, x6, x7
1   0.06011071  NA  NA  NA  NA  NA  NA
1   NA  0.09756118  NA  NA  NA  NA  NA
1   NA  NA  NA  NA  0.143701    NA  NA
1   NA  NA  NA  NA  NA  0.1584451   NA
1   NA  NA  NA  0.1809486   NA  NA  NA
1   NA  NA  NA  NA  NA  NA  0.1151581
1   NA  NA  -0.1422974  NA  NA  NA  NA", header = TRUE)


#if every column has only one value and the rest are NA's

tibble(plot = 1, map_dfc(df[, -1], ~.[!is.na(.)]))
#> # A tibble: 1 × 8
#>    plot    x1.    x2.    x3.   x4.   x5.   x6.    x7
#>   <dbl>  <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1 0.0601 0.0976 -0.142 0.181 0.144 0.158 0.115

#or gathering and spreading approach

pivot_longer(df,cols = matches('^x\d'), names_to = 'x') %>% 
  filter(!is.na(value)) %>% 
  arrange(x) %>% 
  pivot_wider(names_from = 'x', values_from = 'value')
#> # A tibble: 1 × 8
#>   plot.    x1.    x2.    x3.   x4.   x5.   x6.    x7
#>   <int>  <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1 0.0601 0.0976 -0.142 0.181 0.144 0.158 0.115

reprex package (v2.0.1)

于 2021-11-22 创建