问题
I have the following list:
my_list = list(alpha = list('hi'),
beta = list(1:4, 'how'),
gamma = list(TRUE, FALSE, 'are'))
str(my_list)
List of 3
$ alpha:List of 1
..$ : chr "hi"
$ beta :List of 2
..$ : int [1:4] 1 2 3 4
..$ : chr "how"
$ gamma:List of 3
..$ : logi TRUE
..$ : logi FALSE
..$ : chr "are"
I would like to figure out which data types are contained within each level 1 element. To do this, I can use the following pipeline:
piped = map(my_list, ~map(., class) %>% unique %>% unlist)
str(piped)
List of 3
$ alpha: chr "character"
$ beta : chr [1:2] "integer" "character"
$ gamma: chr [1:2] "logical" "character"
...which works as expected. But when I try to nest the call to unique
inside unlist()
, I get something different:
composite = map(my_list, ~map(., class) %>% unlist(unique(.)))
str(composite)
List of 3
$ alpha: chr "character"
$ beta : chr [1:2] "integer" "character"
$ gamma: chr [1:3] "logical" "logical" "character"
Could someone please help me understand why these two approaches are not equivalent?
回答1:
It's easier to see what's happening if you use anonymous functions rather than the dot notation.
piped = map(my_list, ~map(., class) %>% unique %>% unlist)
is the same as
piped = map(my_list, function (x) map(x, class) %>% unique %>% unlist)
The pipe then places the output of each step in the first position of each subsequent function, so it becomes
piped = map(my_list, function (x) unique(map(x, class)) %>% unlist)
and then
piped = map(my_list, function (x) unlist(unique(map(x, class))))
Which results is
str(piped)
List of 3
$ alpha: chr "character"
$ beta : chr [1:2] "integer" "character"
$ gamma: chr [1:2] "logical" "character"
Similarly composite = map(my_list, ~map(., class) %>% unlist(unique(.)))
can be written as
composite = map(my_list, function(x) map(x, class) %>% unlist(unique(x)))
The two uses of x on both sides of the pipe is where things go weird. I think you were expecting the pipe to place the output of the inner map call in place of the x within the unique
call, but the second x takes the output from the outer map function. Instead the pipe does its default action and places the output of the inner map call in the first position of the unlist
function, like so
composite = map(my_list, function(x) unlist(map(x, class),unique(x)))
Which gives you
str(composite)
List of 3
$ alpha: chr "character"
$ beta : chr [1:2] "integer" "character"
$ gamma: chr [1:3] "logical" "logical" "character"
来源:https://stackoverflow.com/questions/57840592/r-composite-functions-vs-piped-functions-in-purrrmap