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

时间:2017-08-04 20:43:23

标签: r coalesce tidyverse

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

使用以下数据

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解决方案。谢谢!

6 个答案:

答案 0 :(得分: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

答案 1 :(得分:5)

我还没弄明白如何将var movedFrameView:CGRect? { get { return objc_getAssociatedObject(self, &AssociatedKeys.movedFrameView) as? CGRect } set { objc_setAssociatedObject(self, &AssociatedKeys.movedFrameView, newValue, .OBJC_ASSOCIATION_COPY) } } 函数放在coalesce_by_column管道中,但这样做有效:

dplyr

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

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

答案 2 :(得分: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

答案 3 :(得分:2)

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

library(dplyr)
library(tidyr)

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

答案 4 :(得分: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”列和变量名称分组。第三,它删除重复的值。最后,它将数据恢复为其原始的宽格式。

答案 5 :(得分:0)

这与@Oriol Mirosa的答案在功能上相同,而无需自定义功能:

编辑:必须按照@thelatemail的注释省略NA。 @MrFlick也在上面链接的重复线程中给出了答案。

df %>% group_by(A) %>% summarise_all(~first(na.omit(.)))

我想添加此内容,因为它似乎对我来说是定期出现的,并且我已经多次重新讨论了该主题。 @Oriol Mirosa的答案行得通,但是我对此很反感,因为它太复杂了以至于难以记住(因此我回到了该主题)。

就个人而言,我也不喜欢编写不需要的小型自定义函数。尝试用实际的coalesce_by_column调用代替coalesce会导致类型错误(我发现这很奇怪,因为行之间并不交互,而是相互影响)。可以先做mutate_all(as.character)来解决此问题,但是我的目标是最大程度地减少语法,以便在运行时轻松记住它。

此外,此替换会更改行为,以使列中的不相同值引发错误(为什么功能在某些情况下有时会略有不同,这超出了我的理解)。在某些情况下,这种行为可能是更可取的,但是在那种情况下,我建议使用@Jerry T的解决方案,因为它没有自定义函数,并且所使用的函数是熟悉的,可读的,并且它们的顺序(na.omit和{{1 }})不相关。