合并包含NA的数据框中的行以生成完整的行

问题描述 投票:6回答:5

我知道这是一个重复的Q但我似乎无法再找到这个帖子

使用以下数据

df <- data.frame(A=c(1,1,2,2),B=c(NA,2,NA,4),C=c(3,NA,NA,5),D=c(NA,2,3,NA),E=c(5,NA,NA,4))

  A  B  C  D  E
  1 NA  3 NA  5
  1  2 NA  2 NA
  2 NA NA  3 NA
  2  4  5 NA  4

通过A分组,我想使用tidyverse解决方案进行以下输出

  A  B  C  D  E
  1  2  3  2  5
  2  4  5  3  4

我在A有很多小组。我想我看到了使用coalesce的答案,但我不确定如何让它工作。我想要一个与characters一起使用的解决方案。谢谢!

r coalesce tidyverse
5个回答
5
投票

不是tidyverse,而是这里的一个基础R解决方案

df <- data.frame(A=c(1,1),B=c(NA,2),C=c(3,NA),D=c(NA,2),E=c(5,NA))
sapply(df, function(x) x[!is.na(x)][1])
#A B C D E 
#1 2 3 2 5 

随着更新的数据

do.call(rbind, lapply(split(df, df$A), function(a) sapply(a, function(x) x[!is.na(x)][1])))
#  A B C D E
#1 1 2 3 2 5
#2 2 4 5 3 4

6
投票

我还没弄明白如何将coalesce_by_column函数放在dplyr管道中,但是这样可行:

coalesce_by_column <- function(df) {
  return(coalesce(df[1], df[2]))
}

df %>%
  group_by(A) %>%
  summarise_all(coalesce_by_column)

##       A     B     C     D     E
##   <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     1     2     3     2     5
## 2     2     4     5     3     4

编辑:包括@Jon Harmon的超过2名成员的解决方案

# Supply lists by splicing them into dots:
coalesce_by_column <- function(df) {
  return(dplyr::coalesce(!!! as.list(df)))
}

df %>%
  group_by(A) %>%
  summarise_all(coalesce_by_column)

#> # A tibble: 2 x 5
#>       A     B     C     D     E
#>   <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     2     3     2     5
#> 2     2     4     5     3     4

3
投票

这是一个更通用的解决方案(使用uniquena.omit来创建coalesce),它可以处理两行以上的重叠信息。超级简单和前进。

> df <- data.frame(A=c(1,1,2,2,2),B=c(NA,2,NA,4,4),C=c(3,NA,NA,5,NA),D=c(NA,2,3,NA,NA),E=c(5,NA,NA,4,4))

> df
  A  B  C  D  E
1 1 NA  3 NA  5
2 1  2 NA  2 NA
3 2 NA NA  3 NA
4 2  4  5 NA  4
5 2  4 NA NA  4

> df %>% group_by(A) %>% summarise_all(funs( na.omit(unique(.)) ))
# A tibble: 2 x 5
      A     B     C     D     E
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     2     3     2     5
2     2     4     5     3     4

2
投票

我们可以使用fill来填充所有缺失的值。然后为每个组过滤一行。

library(dplyr)
library(tidyr)

df2 <- df %>%
  group_by(A) %>%
  fill(everything(), .direction = "down") %>%
  fill(everything(), .direction = "up") %>%
  slice(1)

0
投票

不同的tidyverse可能是:

df %>%
 gather(var, val, -A, na.rm = TRUE) %>%
 group_by(A, var) %>%
 distinct(val) %>%
 spread(var, val)

      A     B     C     D     E
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     2     3     2     5
2     2     4     5     3     4

首先,它执行从长到长的数据转换,不包括“A”列并删除缺失值。其次,它按“A”列和变量名称分组。第三,它删除重复的值。最后,它将数据返回到其原始的宽格式。

© www.soinside.com 2019 - 2024. All rights reserved.