如何使用dplyr中的map2()mutate()列列表

时间:2017-12-07 19:56:35

标签: r dplyr purrr

我最近不得不编译学生分数的数据框(每个学生一行,id列和几个整数值列,每个分数一个)。我必须结合一个"大师"数据框和几个"校正"数据框(主要包含NA和对主服务器的一些更新),以便结果包含主服务器的最大值和所有更正。

我成功通过复制粘贴一系列mutate()个调用,这有效(见下面的例子),但在我看来并不优雅。我想要做的是,而不是复制和粘贴,使用map2和两列列的内容来逐对比较列。像(显然不能这样)的东西:

list_of_cols1 <- list(col1.x, col2.x, col3.x)
list_of_cols2 <- list(col1.y, col2.y, col3.y
map2(list_of_cols1, list_of_cols2, ~ column = pmax(.x, .y, na.rm=T))

我似乎无法理解这样做。我的问题是:如何指定这样的列列表并在map2()管道中的dplyr调用中对其进行变更,或者甚至是可能的 - 我是否完全错了?

最低工作实例

library(tidyverse)

master <- tibble(
  id=c(1,2,3), 
  col1=c(1,1,1),
  col2=c(2,2,2),
  col3=c(3,3,3)
)
correction1 <- tibble(
  id=seq(1,3),
  col1=c(NA, NA, 2 ),
  col2=c( 1, NA, 3 ),
  col3=c(NA, NA, NA)
)

result <- reduce(
  # Ultimately there would several correction data frames
  list(master, correction1), 
  function(x,y) {
    x <- x %>% 
      left_join(
        y,
        by = c("id")
      ) %>%
      # Wish I knew how to do this mutate call with map2 
      mutate(
        col1 = pmax(col1.x, col1.y, na.rm=T), 
        col2 = pmax(col2.x, col2.y, na.rm=T), 
        col3 = pmax(col3.x, col3.y, na.rm=T)
      ) %>%
      select(id, col1:col3)
  }
)

结果是

> result
# A tibble: 3 x 4
     id  col1  col2  col3
  <int> <dbl> <dbl> <dbl>
1     1     1     2     3
2     2     1     2     3
3     3     2     3     3

3 个答案:

答案 0 :(得分:0)

而不是执行left_join,只需绑定行然后进行汇总。例如

result <- reduce(
  list(master, master), 
  function(x,y) {
    bind_rows(x, y) %>%
      group_by(id) %>%
      summarize_all(max, na.rm=T)
  }
)
result
#     id  col1  col2  col3
#   <dbl> <dbl> <dbl> <dbl>
# 1     1     1     2     3
# 2     2     1     2     3
# 3     3     2     3     3

实际上,您甚至不需要缩减,因为bind_rows可以列出

添加另一张表

correction2 <- tibble(id=2,col1=NA,col2=8,col3=NA)
bind_rows(master, correction1, correction2) %>% 
  group_by(id) %>%
  summarize_all(max, na.rm=T)

答案 1 :(得分:0)

很抱歉,我们没有回答您关于map2的问题,我发现在行上汇总比在tidy R中的列更容易:

library(dplyr)

master <- tibble(
  id=c(1,2,3), 
  col1=c(1,1,1),
  col2=c(2,2,2),
  col3=c(3,3,3)
)
correction1 <- tibble(
  id=seq(1,3),
  col1=c(NA, NA, 2 ),
  col2=c( 1, NA, 3 ),
  col3=c(NA, NA, NA)
)

result <- list(master, correction1) %>% 
  bind_rows() %>% 
  group_by(id) %>% 
  summarise_all(max, na.rm = TRUE)

result
#> # A tibble: 3 x 4
#>      id  col1  col2  col3
#>   <dbl> <dbl> <dbl> <dbl>
#> 1     1     1     2     3
#> 2     2     1     2     3
#> 3     3     2     3     3

答案 2 :(得分:0)

如果correction表格总是与master具有相同的结构,您可以执行以下操作:

library(dplyr)
library(purrr)

update_master = function(...){
  map(list(...), as.matrix) %>%
    reduce(pmax, na.rm = TRUE) %>%
    data.frame()
}

update_master(master, correction1)

要允许id获取字符值,请进行以下修改:

update_master = function(x, ...){
  map(list(x, ...), function(x) as.matrix(x[-1])) %>%
    reduce(pmax, na.rm = TRUE) %>%
    data.frame(id = x[[1]], .)
}

update_master(master, correction1)

<强>结果:

  id col1 col2 col3
1  1    1    2    3
2  2    1    2    3
3  3    2    3    3