Создать приборную функцию множественного уменьшения - PullRequest
0 голосов
/ 07 июня 2019

Я хотел бы заменить это (want) на функцию:

library(tidyverse)
library(rlang)

set.seed(1)
create_a <- function() {
      list(x = 1:10, y = data.frame(aa = round(rnorm(10, 2000, 10), 0),
                                bb = sample(letters[3:8], 10, replace = T),
                                stringsAsFactors = F))
}

create_b <- function() {
  list(x = 1:10, y = data.frame(aa = round(rnorm(10, 10, 1), 0),
                                bb = sample(letters[3:8], 10, replace = T),
                                stringsAsFactors = F))
}  

want <- list(x = reduce(map(list(create_a(), create_b()), 1), c),
             y = reduce(map(list(create_a(), create_b()), 2), rbind)) # or bind_rows

Существует несколько функций (create_a и create_b), которые создают выходные списки с элементами с одинаковыми именами. В отличие от приведенных выше примеров, расчеты в реальных функциях весьма различны. Функция должна выглядеть так:

multiple_reduce <- function(...) {
  # ????
}
want <- multiple_reduce(create_a(), 
                        create_b())

Как вы делаете это, используя аккуратный подход?

want должно выглядеть так в обоих случаях:

$x
 [1]  1  2  3  4  5  6  7  8  9 10  1  2  3  4  5  6  7  8  9 10

$y
     aa bb
1  2014  e
2  1999  g
3  2004  e
4  1999  d
5  1986  g
6  1996  d
7  1996  g
8  1999  c
9  2011  d
10 2008  c
11    9  h
12   10  g
13   11  e
14   10  e
15   11  c
16   10  c
17    9  g
18   10  c
19    9  e
20   11  f

1 Ответ

3 голосов
/ 07 июня 2019

Может быть, одним из способов было бы объединить все входные данные и разделить их на основе их имени, чтобы у нас был список с похожими именами вместе. Затем мы можем проверить, являются ли списки атомарным типом и объединить их как один вектор или фрейм данных соответственно.

library(tidyverse)

multiple_reduce <- function(a, b, ...) {
   combine_list <- c(a, b, ...)
   new_list <- split(combine_list, names(combine_list))
   list(x = map(new_list, ~keep(., is.atomic)) %>% flatten %>% reduce(c),
        y = map(new_list, ~discard(., is.atomic)) %>% flatten %>% bind_rows)
}

multiple_reduce(create_a(), create_b())

#$x
# [1]  1  2  3  4  5  6  7  8  9 10  1  2  3  4  5  6  7  8  9 10

#$y
#     aa bb
#1  2001  g
#2  1998  h
#3  2003  g
#4  1971  h
#5  1998  h
#6  2001  f
#7  1993  d
#8  1990  c
#9  2009  d
#10 2019  d
#11   10  h
#12    9  d
#13   10  g
#14    8  f
#15   11  e
#16    9  c
#17   12  c
#18   10  f
#19   10  c
#20    8  h

Это также будет работать с несколькими такими списками

multiple_reduce(create_a(), create_b(), create_a(), create_b())
...