【问题标题】:How to use purrr:map() and rlang to emulate a pipe chain如何使用 purrr:map() 和 rlang 来模拟管道链
【发布时间】:2019-06-21 00:05:37
【问题描述】:

有几个包,例如 leafletmagick,它们采用特殊对象(分别为地图或图像),并允许使用管道链修改/添加它们。

我想使用带有函数参数的小标题列表来获得相同的行为,但我正在努力解决如何做到这一点,因为purrr::map() 的输出是一个列表(或 dfr 等,但不是传单地图或图片)。

(请注意,过了一会儿,我找到了一种在 magick 中执行此操作的方法,但它仅在 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")

#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.

reprex package (v0.2.1) 于 2019 年 1 月 27 日创建

【问题讨论】:

    标签: r purrr rlang r-leaflet magick-r-package


    【解决方案1】:

    你可以使用purrr::reduce2

    library(purrr)
    reduce2(locations$box, locations$offset,
        ~image_composite(., get(..2), offset = ..3, operator = "over"), .init = x)
    

    【讨论】:

    • 啊,是的,我的解决方案基本上使用partialcompose 和胶带重新发明了reduce 操作。 >.
    【解决方案2】:

    您可以使用purrr::partial 生成具有offsetoperator 等预先指定值的函数列表。然后可以通过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)
    

    【讨论】:

      猜你喜欢
      • 2018-08-20
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多