【问题标题】:Merging two df in r replace missing values在 r 中合并两个 df 替换缺失值
【发布时间】:2019-05-21 16:05:45
【问题描述】:

我想在 R 中匹配两个相似的数据框。两个 dfs 都有部分相同的变量和一个键 (id),其中包含缺失值:

library(tidyverse)

df1 <- as_tibble(list(id = seq(1:6),
                      v1 = c(1, 0, NA, 1, 0, NA),
                      v2 = c(NA, NA, 0, 0, 1, NA),
                      v3 = c(1, 0 , 1, 1, 1, NA)))
df1
# A tibble: 6 x 4
     id    v1    v2    v3
  <int> <dbl> <dbl> <dbl>
1     1     1    NA     1
2     2     0    NA     0
3     3    NA     0     1
4     4     1     0     1
5     5     0     1     1
6     6    NA    NA    NA

df2 <- as_tibble(list(id = seq(1:6),
                      v1 = c(1, NA, 0, 1, 0, 1),
                      v2 = c(1, 0, 0, NA, 1, 1),
                      v4 = c(0, 1, 0, NA, NA, NA)))

df2
# A tibble: 6 x 4
     id    v1    v2    v4
  <int> <dbl> <dbl> <dbl>
1     1     1     1     0
2     2    NA     0     1
3     3     0     0     0
4     4     1    NA    NA
5     5     0     1    NA
6     6     1     1    NA

我想将它们合并成一个如下所示的 df:

     id    v1    v2    v3    v4
  <int> <dbl> <dbl> <dbl> <dbl>
1     1     1     1     1     0
2     2     0     0     0     1
3     3     0     0     1     0
4     4     1     0     1    NA
5     5     0     1     1    NA
6     6     1     1    NA    NA

到目前为止,我已经尝试了各种来自 dplyr 的连接,但不知何故我没有得到它。

【问题讨论】:

  • 如果使用id列进行合并,匹配列v1和v2的合并规则是什么?您是取 df1 还是 df2 的平均值、求和值?
  • 对于第 v2 行第 6 列中的预期结果,它说不适用,这应该是 1 吗?
  • Dave2e:它应该是任何有效值,来自 df1 或 df2。
  • MKa:你说得对,改正了。

标签: r merge


【解决方案1】:

比我的第一个更好的答案:

bind_rows(df1, df2) %>%
  group_by(id) %>%
  summarise_all(~ coalesce(.[1], .[2]))

## A tibble: 6 x 5
#      id    v1    v2    v3    v4
#   <int> <dbl> <dbl> <dbl> <dbl>
# 1     1     1     1     1     0
# 2     2     0     0     0     1
# 3     3     0     0     1     0
# 4     4     1     0     1    NA
# 5     5     0     1     1    NA
# 6     6     1     1    NA    NA

【讨论】:

  • 非常好,完全符合我的要求,即使添加更多变量和不同长度的 dfs 也是如此。你能解释一下,你在coalesce() 中究竟索引了什么?
【解决方案2】:

我们可以在使用通用名称拆分后在共享列上使用dplyr::coalesce。然后map“循环”通过具有多于一列的dfs和mutate使用coalesce

library(dplyr)
library(purrr)
df1 %>% left_join(df2, by='id') %>% 
        split.default(gsub('.[xy]','',names(.))) %>% 
        map_dfc(~if(ncol(.x)==1) .x else 
                mutate(.x, !!sym(gsub('.x','',names(.x)[1])):=coalesce(!!!syms(names(.x))))) %>% 
        select(-contains('.'))

# A tibble: 6 x 5
       id    v1    v2    v3    v4
     <int> <dbl> <dbl> <dbl> <dbl>
  1     1     1     1     1     0
  2     2     0     0     0     1
  3     3     0     0     1     0
  4     4     1     0     1    NA
  5     5     0     1     1    NA
  6     6     1     1    NA    NA

这里有一个简单的例子说明symsyms 对每个包含 .x 和 .y 列的变量所做的事情,例如这里v1coalesce 支持 tidy dot 功能,因此我们使用 !!!syms

df_sub <- df1 %>% left_join(df2, by='id') %>% select(v1.x, v1.y)
# . represents df_sub
nm <- gsub('.x','',names(df_sub)[1])
nms <- names(df_sub)
df_sub %>% mutate(!!sym(nm) := coalesce(!!!syms(nms)))

# A tibble: 6 x 3
  v1.x  v1.y    v1
  <dbl> <dbl> <dbl>
1     1     1     1
2     0    NA     0
3    NA     0     0
4     1     1     1
5     0     0     0
6    NA     1     1

symsyms 这些函数将字符串作为输入并将它们转换为符号,然后我们使用!!!!! 将它们取消引用。我们使用:=,因为我们需要在mutate 中使用字符串作为列名,请参阅我的回答here。阅读更多关于symsyms!!!!!here的信息

【讨论】:

  • 您能解释一下sym 代码是怎么回事吗?它非常密集
【解决方案3】:

这是另一种方式,类似于@utubun 使用bind_rowssummarise 的方法。

bind_rows(df1, df2) %>%
  group_by(id) %>%
  summarise_all(list(~mean(., na.rm = TRUE))) %>% 
  # convert NaN to NA (if required)
  mutate_at(vars(-id), function(x) ifelse(is.nan(x), NA, x))

【讨论】:

  • 工作正常,请问为什么 mean 函数有效?
  • 你可能会使用sum,但sum(c(NA, NA), na.rm = TRUE)会给你0,而mean(c(NA, NA), na.rm = TRUE)会给你NaN。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 2020-08-10
相关资源
最近更新 更多