Как использовать purrr: map () и rlang для эмуляции цепочки труб - PullRequest
0 голосов
/ 28 января 2019

Существует несколько пакетов, таких как leaflet или magick, которые принимают специальные объекты (карты или изображения соответственно) и позволяют изменять их / добавлять в цепочку труб.

Я быЯ хотел бы получить то же поведение, используя список элементов с аргументами функции, но я борюсь с тем, как это сделать, поскольку выходные данные из purrr::map() являются списком (или dfr и т. д., но не листовой картой или изображением).

(Обратите внимание, что я нашел способ сделать это в магии через некоторое время, но он работает только в magick из-за использования некоторых специальных функций способом, который они не предназначены для использования, поэтомуЯ все еще ищу общий ответ на этот вопрос для других пакетов, таких как leaflet)

Представляет:

suppressPackageStartupMessages(require(tidyverse))
suppressPackageStartupMessages(require(magick))
suppressPackageStartupMessages(require(rlang))


x <- image_blank(100, 100, "yellow")

blackbox <- image_blank(10, 10, "black")
redbox <- image_blank(10, 10, "red")

locations <- tribble(~box, ~offset,
                      "redbox", "+0+0",
                      "redbox", "+90+0",
                      "redbox", "+0+90",
                      "redbox", "+90+90",
                      "blackbox", "+40+40",
                      "blackbox", "+50+50",
                      "blackbox", "+30+60",
                      "blackbox", "+60+30")

#preferred method:
locations %>% 
  mutate(row = row_number()) %>% 
  split(.$row) %>% 
  map(function(location) {
    x <- x %>% image_composite(eval_tidy(sym(location$box)), offset = location$offset, operator = "over")
  })
#> $`1`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`2`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`3`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`4`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`5`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`6`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`7`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72  
#> 
#> $`8`
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 png      100    100 sRGB       FALSE        0 72x72




#desired result I'm trying to emulate:
x %>% 
  image_composite(redbox, offset = "+0+0", operator = "over") %>% 
  image_composite(redbox, offset = "+90+0", operator = "over") %>% 
  image_composite(redbox, offset = "+0+90", operator = "over") %>% 
  image_composite(redbox, offset = "+90+90", operator = "over") %>% 
  image_composite(blackbox, offset = "+40+40", operator = "over") %>% 
  image_composite(blackbox, offset = "+50+50", operator = "over") %>% 
  image_composite(blackbox, offset = "+30+60", operator = "over") %>% 
  image_composite(blackbox, offset = "+60+30", operator = "over")

image

#as an aside, i figured out to do it part of the way with magick, but does not apply to the general question and doesn't fully emulate the above.
y <- image_blank(100, 100, "transparent")

locations %>% 
  mutate(row = row_number()) %>% 
  split(.$row) %>% 
  map(function(location) {
    y %>% image_composite(eval_tidy(sym(location$box)), offset = location$offset, operator = "over")
  }) %>% 
  reduce(c) %>% 
  image_flatten() %>% 
  image_background(color = "yellow") #also having to flatten an animation loses the transparency, so you can't add it on top of the background.

image

Created on 2019-01-27 by the Представить пакет (v0.2.1)

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

Вы можете использовать purrr::reduce2:

library(purrr)
reduce2(locations$box, locations$offset,
    ~image_composite(., get(..2), offset = ..3, operator = "over"), .init = x)
0 голосов
/ 01 апреля 2019

Вы можете использовать purrr::partial для генерации списка функций с предварительно заданными значениями для offset, operator и т. Д. Затем эти функции можно объединить в одну операцию с помощью purrr::compose:

funs <- map2( locations$box, locations$offset,
         ~partial(image_composite, composite_image=get(.x), 
                  offset=.y, operator="over") )

## Equivalent to x %>% funs[[1]]() %>% funs[[2]]() %>% ...
compose(!!!funs)(x)
...