简体   繁体   中英

R ggplot2: How to draw geom_points that have a solid color and a transparent stroke and are colored depending on color?

I would like to make a scatter plot where every point gets a sphere. Both the dot and its sphere are colored according to some column values.

A minimal example that shows what I want:

library(ggplot2)
library(vcd) # only needed for example dataset
ggplot(Arthritis, aes(x = ID, y = Age)) + 
    geom_point(aes(color=Sex), size=10, alpha=.3) + 
    geom_point(aes(color=Treatment), size=3)

在此处输入图像描述

The problem with this "solution" is that using two geom_point layers seems to mess up the legend. I guess it would also make much more sense to only have one geom_point layer and use a shape that also adds a stroke, so something like this:

ggplot(Arthritis, aes(x = ID, y = Age)) + 
    geom_point(aes(color=Sex, fill=Treatment), shape=21, size=5, stroke=5)

在此处输入图像描述 Here the legend makes way more sense, however, I can not figure out how to make the stroke transparent. This is important because you just can not see anything anymore when points overlap.

Answers like this do not solve my problem, because they use a constant color and thus can use the function alpha . However, I can not figure out if and how to use this with colors that depend on the data.

TL;DR: How can I draw geom_points that have a solid color and a transparent stroke but not constant colors?

You are on the right track to recognize that you can use the function alpha() , and have realized that you cannot just put alpha() within aes() . You can, however, pass alpha() as the values= argument within any scale_* functions. Here's an example using mtcars :

ggplot(mtcars, aes(mpg, disp)) + 
  geom_point(
    aes(color=factor(cyl), fill=factor(carb)),
    shape=21, size=4, stroke=4) +
  scale_color_manual(values=alpha(rainbow(3), 0.2))

在此处输入图像描述

One problem with that is those big black lines around the " factor(carb) legend don't sit well with me. Super ew. You can get rid of them using the guides() function and using override.aes= to specify what you want shown there and what to replace it with. In this case, you can set the color=NA to override the inherited aesthetic to be transparent (leaving only the fill= part).

ggplot(mtcars, aes(mpg, disp)) + 
  geom_point(
    aes(color=factor(cyl), fill=factor(carb)),
    shape=21, size=4, stroke=4) +
  scale_color_manual(values=alpha(rainbow(3), 0.2)) +
  guides(fill=guide_legend(override.aes = list(color=NA))) +
  labs(color="cyl", fill="carb")

在此处输入图像描述

BTW, there's no simple way to place the stroke "behind" the fill part for geom_point . You can probably write your own custom stat/geom for doing that, but geom_point is always drawn with fill first, then stroke.

A simple way round this is to make it so that the larger transparent circles aren't points at all, but filled circles. That way you can use the fill aesthetic to label them. This uses geom_circle from ggforce :

library(ggplot2)
library(vcd)
library(ggforce)

ggplot(Arthritis) + 
  geom_circle(aes(x0 = ID, y0 = Age, r = 2, fill = Sex), alpha = .3, colour = NA) +
  geom_point(aes(x = ID, y = Age, color = Treatment), size = 3) + 
  coord_equal() + 
  scale_color_discrete(h = c(350, 190))

Created on 2020-07-01 by the reprex package (v0.3.0)

Or make a second color scale!

library(ggplot2)
library(vcd) 
#> Loading required package: grid
library(ggnewscale)

ggplot(Arthritis, aes(x = ID, y = Age)) + 
  ## removing stroke so it does not have this awkward border around it
  geom_point(aes(color=Sex), size=10, alpha=.3, stroke = 0) +
  new_scale_color()+
  geom_point(aes(color=Treatment), size=3) 

Created on 2022-06-15 by the reprex package (v2.0.1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM