【问题标题】:Same/Fix alpha even for overlapping areas in ggplot2即使对于 ggplot2 中的重叠区域,相同/修复 alpha
【发布时间】:2022-08-18 19:24:05
【问题描述】:

我想先画一堆区域,然后用相同的单个 alpha 值显示生成的整体区域。所以代替这个:

library(tidyverse)

dat <- tribble(
  ~xmin, ~xmax, ~ymin, ~ymax,
     10,    30,    10,    30,
     20,    40,    20,    40,
     15,    35,    15,    25,
     10,    15,    35,    40
)

ggplot() +
  geom_rect(data = dat,
            aes(
              xmin = xmin,
              xmax = xmax,
              ymin = ymin,
              ymax = ymax
            ),
            alpha = 0.5)

我希望将其作为我的结果:

reprex package (v2.0.1) 于 2022 年 7 月 26 日创建

我觉得我的问题的答案可能与this thread 中的答案相似,但我并不完全理解,因此不确定。另请注意,我使用geom_rect() 作为reprex,但最终我希望它适用于ggforce::geom_circle()

编辑 1

不幸的是,指向scale_alpha(range = ..., limits = ...)Quinten\'s first answer 没有回答我的问题,因为它显然只能导致不透明的区域。

编辑 2

Quinten\'s updated answer 是我可以接受的上述代表的解决方法。但是,正如我在上面提到的,我希望它适用于ggforce::geom_circle()。不幸的是,我想我现在必须更具体并创建另一个代表。 (对不起)

library(ggforce)
#> Lade nötiges Paket: ggplot2

dat <- data.frame(
  x = c(1, 1.3, 1.6),
  y = c(1, 1, 1),
  circle = c(\"yes\", \"yes\", \"no\")
)

ggplot() +
  coord_equal() +
  theme_classic() +
  geom_circle(
    data = subset(dat, circle == \"yes\"),
    aes(x0 = x, y0 = y, r = 0.5, alpha = circle),
    fill = \"grey\",
    color = NA,
    show.legend = TRUE
  ) +
  geom_point(
    data = dat,
    aes(x, y, color = circle)
  ) +
  scale_color_manual(
    values = c(\"yes\" = \"blue\", \"no\" = \"red\")
  ) +
  scale_alpha_manual(
    values = c(\"yes\" = 0.25, \"no\" = 0)
  )

reprex package (v2.0.1) 创建于 2022-08-17

    标签: r ggplot2 alpha ggforce


    【解决方案1】:

    ggblend

    不久前我还看到了ggblend,但不确定它是否能解决您的问题,幸运的是它可以解决!你可以做两件事:

    1. 您可以将 Rstudio 中的 Graphics 更改为“Cairo”,如下所示:

      代码:

      #remotes::install_github("mjskay/ggblend")
      library(ggblend)
      library(ggforce)
      
      # reprex 1 ----------------------------------------------------------------
      library(tidyverse)
      
      dat <- tribble(
        ~xmin, ~xmax, ~ymin, ~ymax,
        10,    30,    10,    30,
        20,    40,    20,    40,
        15,    35,    15,    25,
        10,    15,    35,    40
      )
      
      p1 <- ggplot() +
        geom_rect(data = dat,
                  aes(
                    xmin = xmin,
                    xmax = xmax,
                    ymin = ymin,
                    ymax = ymax
                  ),
                  alpha = 0.3) %>% blend("source")
      
      p1
      

      # reprex 2 ----------------------------------------------------------------
      dat <- data.frame(
        x = c(1, 1.3, 1.6),
        y = c(1, 1, 1),
        circle = c("yes", "yes", "no")
      )
      
      p2 <- ggplot() +
        coord_equal() +
        theme_classic() +
        geom_circle(
          data = subset(dat, circle == "yes"),
          aes(x0 = x, y0 = y, r = 0.5, alpha = circle),
          fill = "grey",
          color = NA,
          show.legend = TRUE
        ) %>% blend("source") +
        geom_point(
          data = dat,
          aes(x, y, color = circle)
        ) +
        scale_color_manual(
          values = c("yes" = "blue", "no" = "red")
        ) +
        scale_alpha_manual(
          values = c("yes" = 0.25, "no" = 0)
        )
      
      p2
      #ggsave(plot = p2, "p2.pdf", device = cairo_pdf)
      

      1. 您可以将对象保存为pngtype = "cairo",如下所示:
      library(ggblend)
      library(ggforce)
      
      # reprex 1 ----------------------------------------------------------------
      library(tidyverse)
      
      dat <- tribble(
        ~xmin, ~xmax, ~ymin, ~ymax,
        10,    30,    10,    30,
        20,    40,    20,    40,
        15,    35,    15,    25,
        10,    15,    35,    40
      )
      
      p1 <- ggplot() +
        geom_rect(data = dat,
                  aes(
                    xmin = xmin,
                    xmax = xmax,
                    ymin = ymin,
                    ymax = ymax
                  ),
                  alpha = 0.3) %>% blend("source")
      #> Warning: Your graphics device, "quartz_off_screen", reports that blend = "source" is not supported.
      #>  - If the blending output IS NOT as expected (e.g. geoms are not being
      #>    drawn), then you must switch to a graphics device that supports
      #>    blending, like png(type = "cairo"), svg(), or cairo_pdf().
      #>  - If the blending output IS as expected despite this warning, this is
      #>    likely a bug *in the graphics device*. Unfortunately, several
      #>    graphics do not correctly report their capabilities. You may wish to
      #>    a report a bug to the authors of the graphics device. In the mean
      #>    time, you can disable this warning via options(ggblend.check_blend =
      #>    FALSE).
      #>  - For more information, see the Supported Devices section of
      #>    help('blend').
      
      png(filename = "plot1.png", type = "cairo")
      # Output in your own folder:
      
      p1
      dev.off()
      

      2

      #ggsave(plot = p1, "p1.pdf", device = cairo_pdf)
      
      # reprex 2 ----------------------------------------------------------------
      dat <- data.frame(
        x = c(1, 1.3, 1.6),
        y = c(1, 1, 1),
        circle = c("yes", "yes", "no")
      )
      
      p2 <- ggplot() +
        coord_equal() +
        theme_classic() +
        geom_circle(
          data = subset(dat, circle == "yes"),
          aes(x0 = x, y0 = y, r = 0.5, alpha = circle),
          fill = "grey",
          color = NA,
          show.legend = TRUE
        ) %>% blend("source") +
        geom_point(
          data = dat,
          aes(x, y, color = circle)
        ) +
        scale_color_manual(
          values = c("yes" = "blue", "no" = "red")
        ) +
        scale_alpha_manual(
          values = c("yes" = 0.25, "no" = 0)
        )
      #> Warning: Your graphics device, "quartz_off_screen", reports that blend = "source" is not supported.
      #>  - If the blending output IS NOT as expected (e.g. geoms are not being
      #>    drawn), then you must switch to a graphics device that supports
      #>    blending, like png(type = "cairo"), svg(), or cairo_pdf().
      #>  - If the blending output IS as expected despite this warning, this is
      #>    likely a bug *in the graphics device*. Unfortunately, several
      #>    graphics do not correctly report their capabilities. You may wish to
      #>    a report a bug to the authors of the graphics device. In the mean
      #>    time, you can disable this warning via options(ggblend.check_blend =
      #>    FALSE).
      #>  - For more information, see the Supported Devices section of
      #>    help('blend').
      
      png(filename = "plot2.png", type = "cairo")
      
      # Output in your folder
      p2
      

      dev.off()
      #ggsave(plot = p2, "p2.pdf", device = cairo_pdf)
      

      创建于 2022 年 8 月 17 日,reprex v2.0.2

      更新

      您可以做的是使用sf 包中的st_union 对区域进行UNION,这样您就可以得到一个区域,而不是像这样的重叠区域:

      library(tidyverse)
      library(sf)
      
      dat <- tribble(
        ~xmin, ~xmax, ~ymin, ~ymax,
        10,    30,    10,    30,
        20,    40,    20,    40,
        15,    35,    15,    25,
        10,    15,    35,    40
      )
      
      area1 <- dat %>%
        slice(1) %>%
        as_vector() %>%
        st_bbox() %>%
        st_as_sfc()
      
      area2 <- dat %>%
        slice(2) %>%
        as_vector() %>%
        st_bbox() %>%
        st_as_sfc()
      
      area3 <- dat %>%
        slice(3) %>%
        as_vector() %>%
        st_bbox() %>%
        st_as_sfc()
      
      area4 <- dat %>%
        slice(4) %>%
        as_vector() %>%
        st_bbox() %>%
        st_as_sfc()
      
      all_areas <- st_union(area1, area2) %>%
        st_union(area3) %>%
        st_union(area4)
      
      ggplot(all_areas) +
        geom_sf(alpha = 0.5, fill = "grey", colour = "grey") +
        theme(legend.position = "none")
      

      ggplot(all_areas) +
        geom_sf(alpha = 0.8, fill = "grey", colour = "grey") +
        theme(legend.position = "none")
      

      reprex package (v2.0.1) 于 2022-08-17 创建

      第一个答案

      也许你想要这个,你可以使用 scale_alpharangelimits 来保持相同的区域 alpha 像这样:

      library(tidyverse)
      
      dat <- tribble(
        ~xmin, ~xmax, ~ymin, ~ymax,
        10,    30,    10,    30,
        20,    40,    20,    40,
        15,    35,    15,    25,
        10,    15,    35,    40
      )
      
      ggplot() +
        geom_rect(data = dat,
                  aes(
                    xmin = xmin,
                    xmax = xmax,
                    ymin = ymin,
                    ymax = ymax,
                    alpha = 0.5
                  )) +
        scale_alpha(range = c(0, 1), limits = c(0, 0.5)) +
        theme(legend.position = "none")
      

      reprex package (v2.0.1) 于 2022 年 7 月 26 日创建

    【讨论】:

    • 如果我错了,请纠正我,但这种方法只能使整个区域不透明(alpha = 1),但不能使整个区域具有相同 alpha 值的半透明,例如0.5?
    • @PaulSchmidt,是的,你是对的,所以保持 alpha 0.5 有点棘手。所以这固定有一个区域。
    • @PaulSchmidt,我更新了我的答案。您可以使用sf 包中的st_union 将这些区域合并为一个区域。正如您在答案中看到的那样,alpha 现在是相同的,您甚至可以更改它。
    • 对于我上面的代表,这确实是我会接受的答案。但是,正如您现在在我的第二次编辑中看到的那样,我的 reprex 不够精确是我的错,因为您的解决方案无法转换(我认为?)当我最终想要使用 ggforce::geom_circle() 时。
    【解决方案2】:

    使用sfpurrr

    • 创建多边形列表(矩形)
    • 创建一个多多边形作为这些矩形的联合
    • geom_sf 显示结果
    library(tidyverse)
    library(sf)
    
    dat <- tribble(
      ~xmin, ~xmax, ~ymin, ~ymax,
      10,    30,    10,    30,
      20,    40,    20,    40,
      15,    35,    15,    25,
      10,    15,    35,    40
    )
    
    sf_rectangle <- function(xmin,xmax,ymin,ymax) {
      st_polygon(list(rbind(c(xmin, ymin), c(xmin, ymax), c(xmax, ymax), c(xmax, ymin), c(xmin, ymin))))
    }
    
    rect_union <- dat %>% purrr::pmap(sf_rectangle) %>%
                          purrr::reduce(st_union)
    
    
    ggplot(rect_union) + geom_sf(alpha=.2)
    

    【讨论】:

      【解决方案3】:

      好吧,我偶然发现了{ggblend} 和它的blend() 函数。基本上,我只需要在geom_ 之后添加%&gt;% blend("source"),它将覆盖多个半透明区域,它完全符合我的要求。

      但是,它确实具有以下限制,可以在下面的 reprex 的 Warning 中看到,即您实际上无法在 RStudio 中预览绘图,甚至可能无法将其导出到某些文件类型,因为并非所有设备可以处理这个。但是,通过ggsave(..., device = cairo_pdf) 导出到 pdf 效果很好,我在下面显示了它的屏幕截图。

      不过,我将保留这个问题,直到我找到同时导出 .png.svg 的方法,或者有人提出适用于 reprex 1 和 reprex 2 的替代解决方案。

      # remotes::install_github("mjskay/ggblend")
      library(ggblend)
      library(ggforce)
      library(tidyverse)
      
      
      # reprex 1 ----------------------------------------------------------------
      library(tidyverse)
      
      dat <- tribble(
        ~xmin, ~xmax, ~ymin, ~ymax,
        10,    30,    10,    30,
        20,    40,    20,    40,
        15,    35,    15,    25,
        10,    15,    35,    40
      )
      
      p1 <- ggplot() +
        geom_rect(data = dat,
                  aes(
                    xmin = xmin,
                    xmax = xmax,
                    ymin = ymin,
                    ymax = ymax
                  ),
                  alpha = 0.3) %>% blend("source")
      #> Warning: Your graphics device, "png", reports that blend = "source" is not supported.
      #>  - If the blending output IS NOT as expected (e.g. geoms are not being
      #>    drawn), then you must switch to a graphics device that supports
      #>    blending, like png(type = "cairo"), svg(), or cairo_pdf().
      #>  - If the blending output IS as expected despite this warning, this is
      #>    likely a bug *in the graphics device*. Unfortunately, several
      #>    graphics do not correctly report their capabilities. You may wish to
      #>    a report a bug to the authors of the graphics device. In the mean
      #>    time, you can disable this warning via options(ggblend.check_blend =
      #>    FALSE).
      #>  - For more information, see the Supported Devices section of
      #>    help('blend').
      
      ggsave(plot = p1, "p1.pdf", device = cairo_pdf)
      #> Saving 7 x 5 in image
      

      
      # reprex 2 ----------------------------------------------------------------
      dat <- data.frame(
        x = c(1, 1.3, 1.6),
        y = c(1, 1, 1),
        circle = c("yes", "yes", "no")
      )
      
      p2 <- ggplot() +
        coord_equal() +
        theme_classic() +
        geom_circle(
          data = subset(dat, circle == "yes"),
          aes(x0 = x, y0 = y, r = 0.5, alpha = circle),
          fill = "grey",
          color = NA,
          show.legend = TRUE
        ) %>% blend("source") +
        geom_point(
          data = dat,
          aes(x, y, color = circle)
        ) +
        scale_color_manual(
          values = c("yes" = "blue", "no" = "red")
        ) +
        scale_alpha_manual(
          values = c("yes" = 0.25, "no" = 0)
        )
      #> Warning: Your graphics device, "png", reports that blend = "source" is not supported.
      #>  - If the blending output IS NOT as expected (e.g. geoms are not being
      #>    drawn), then you must switch to a graphics device that supports
      #>    blending, like png(type = "cairo"), svg(), or cairo_pdf().
      #>  - If the blending output IS as expected despite this warning, this is
      #>    likely a bug *in the graphics device*. Unfortunately, several
      #>    graphics do not correctly report their capabilities. You may wish to
      #>    a report a bug to the authors of the graphics device. In the mean
      #>    time, you can disable this warning via options(ggblend.check_blend =
      #>    FALSE).
      #>  - For more information, see the Supported Devices section of
      #>    help('blend').
      
      ggsave(plot = p2, "p2.pdf", device = cairo_pdf)
      #> Saving 7 x 5 in image
      

      创建于 2022 年 8 月 17 日,reprex v2.0.2

      【讨论】:

      • 太好了,您找到了解决方案。我还看到了ggblend 包,不确定它是否适合您的问题。我在答案中添加了一些代码以将输出另存为 png。您可以将pngtype = "cairo" 一起使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多