ggplot2 - 根据因子分配符号填充

时间:2021-11-04 23:42:19

I am relatively new to R and new to ggplot. I have a large data set and would like to make plots where the symbol fill for any given data series on the plot is governed by a factor in the data set. An example data frame is shown below where both "Station" and "Flag" are factors

我是R的新手,也是ggplot的新手。我有一个大型数据集,并且想要绘制图中任何给定数据系列的符号填充由数据集中的因子控制的图。下面示出了示例数据帧,其中“站”和“标志”都是因子

Day Station Value Flag
1       1   0.0    b
2       1   1.0    a
3       1   2.0    a
1       2   2.3    a
2       2   1.0    a
3       2   0.2    b
1       3   0.5    b
2       3   0.5    b
3       3   0.5    b

I can control symbol shape and color using the factor "Station" but also want to control symbol fill using the factor "Flag" where, for example, filled symbols are used for Flag = "a" and open symbols are used for Flag = "b" - any given station will have a mix of filled and open symbols. I can do this in the base plotting functions of R but can't get it to work in ggplot2. This would be very tedious to do for the real data set with many more stations or other factors of interest.

我可以使用因子“Station”控制符号形状和颜色,但也想使用因子“Flag”控制符号填充,例如,填充符号用于Flag =“a”,而开放符号用于Flag =“ b“ - 任何给定的电台都会混合使用填充符号和开放符号。我可以在R的基本绘图功能中执行此操作,但无法在ggplot2中使其工作。对于具有更多站点或其他感兴趣因素的真实数据集来说,这将是非常繁琐的。

As I am new, the system won't let me post images (not enough reputation points) but here is the code I use to generate the figure I am looking for and the failed ggplot attempt - not shown are the numerous variations on "scale_fill_manual" that have not worked.

因为我是新手,系统不会让我发布图像(没有足够的信誉点),但这里是我用来生成我正在寻找的图形和失败的ggplot尝试的代码 - 未显示的是“scale_fill_manual”的众多变体“那没用。

library(ggplot2)
data <- read.table("dfquestion.csv", header = TRUE, sep = ",", na.strings = "",
                  colClasses = c("Day" = "numeric",
                                 "Station" = "factor",
                                 "Value" = "numeric",
                                 "Flag" = "factor"
                                 )
                  )
##---------------------------------------------------
# Select parameter to graph
x.value <- "Day"
y.value <- "Value"
##---------------------------------------------------
# Subset data by Station
##---------------------------------------------------
Sta1 <- subset(data, Station == "1")
Sta2 <- subset(data, Station == "2")
Sta3 <- subset(data, Station == "3")
##---------------------------------------------------
#
# Set symbol colors and background. 
# open symbols/ clear background = value below reporting limit
# Black = Station 1
# Red = Station 2
# Green = Station 3
#
##---------------------------------------------------
bg.list1 <- rep(0,length(Sta1$Flag))
bg.list1[Sta1$Flag == "a"] <- "black"
bg.list1[Sta1$Flag == "b"] <- NA
#
bg.list2 <- rep(0,length(Sta2$Flag))
bg.list2[Sta2$Flag == "a"] <- "red"
bg.list2[Sta2$Flag == "b"] <- NA
#
bg.list3 <- rep(0,length(Sta3$Flag))
bg.list3[Sta3$Flag == "a"] <- "green"
bg.list3[Sta3$Flag == "b"] <- NA
##---------------------------------------------------
#
# Symbol type
# circle = Sta1; pch = 21
# square = Sta2; pch = 22
# triangle = Sta3; pch = 24
#
##---------------------------------------------------
opar <- par(no.readonly=TRUE)
par(oma = c(0,1,0,2.5))
plot(Sta1$Day, Sta1$Value, type = "b", pch = 24, bg = c(bg.list1), cex = 1.2, col = "black",
     xlim = c(min(Sta1$Day), max(Sta1$Day)),
     ylim = c(range(na.omit(Sta1$Value),
                na.omit(Sta2$Value),
                na.omit(Sta3$Value)
                )),
 xlab = x.value,
 ylab = y.value,
 cex.lab = 1.25, cex.axis = 1.25,
 )
points(Sta2$Day, Sta2$Value, type = "b", pch = 21, bg = c(bg.list2), cex = 1.2, col = "red")
points(Sta3$Day, Sta3$Value, type = "b", pch = 22, bg = c(bg.list3), cex = 1.2, col = "green")
###
##---------------------------------------------------
# Creates legend outside primary graph
par(fig = c(0, 1, 0, 1), oma = c(0,0,0,0), mar = c(0,0,0,0), new = TRUE)
plot(0,0, type = "n", xaxt = "n", yaxt = "n")
legend("topright", legend = c(paste("Sta1"),
                     paste("Sta2"),
                     paste("Sta3"),
                     paste(""),
                     paste("above"),
                     paste("below")
                     ),
pch = c(21, 22, 24,
    NA,
    21, 21),
lty = c(NA), lwd = c(NA),
col = c("black", "red", "green",
    NA,
    "red", "red"),
pt.bg = c("black", "red", "green", 
      NA,
      "red", NA
      ),
text.col = "black",
bty = "n", cex = 0.95,
inset=c(-0.01,0.14))
#
par(opar)
#
##---------------------------------------------------
# Attempt to do the same thing in ggplot
#
p <- ggplot(data = data, aes(x=Day, y=Value, shape = Station, color = Station, fill = Flag)) + 
  geom_line(size = 1) + 
  geom_point(size = 4) 
p <- p + scale_shape_manual(values = c(21, 22, 23)) 
p <- p + scale_color_manual(values = c("black", "red", "green"))
# Adjust legend fills - filled = detect, open = non-detect
p <- p + guides(fill = guide_legend(override.aes = list(shape = 21, fill = c("black", NA))))
print(p)

1 个解决方案

#1


1  

I think that alpha might be of use here. I came up with a solution, but I'm not entirely happy with it. I thought alpha would just impact fill for points that need both color and fill but it changed the transparency of both. I ended up adding a second geom_point layer as a work around.

我认为alpha可能在这里有用。我提出了一个解决方案,但我并不完全满意。我认为alpha只会影响需要颜色和填充的点的填充,但它改变了两者的透明度。我最后添加了第二个geom_point图层作为解决方法。

ggplot(data = dat, aes(x=Day, y=Value, shape = Station, fill = Station, color = Station)) + 
    geom_line(size = 1, show_guide = FALSE) + 
    geom_point(size = 4, aes(fill = NULL)) +
    geom_point(size = 4, aes(alpha = Flag)) +
    scale_shape_manual(values = c(21, 22, 23)) +
    scale_color_manual(values = c("black", "red", "green")) +
    scale_fill_manual(values = c("black", "red", "green")) +
    scale_alpha_manual(values = c(1, 0)) +
    guides(alpha = guide_legend(override.aes = list(shape = 21, fill = c("black", NA), alpha = c(1,1))))

#1


1  

I think that alpha might be of use here. I came up with a solution, but I'm not entirely happy with it. I thought alpha would just impact fill for points that need both color and fill but it changed the transparency of both. I ended up adding a second geom_point layer as a work around.

我认为alpha可能在这里有用。我提出了一个解决方案,但我并不完全满意。我认为alpha只会影响需要颜色和填充的点的填充,但它改变了两者的透明度。我最后添加了第二个geom_point图层作为解决方法。

ggplot(data = dat, aes(x=Day, y=Value, shape = Station, fill = Station, color = Station)) + 
    geom_line(size = 1, show_guide = FALSE) + 
    geom_point(size = 4, aes(fill = NULL)) +
    geom_point(size = 4, aes(alpha = Flag)) +
    scale_shape_manual(values = c(21, 22, 23)) +
    scale_color_manual(values = c("black", "red", "green")) +
    scale_fill_manual(values = c("black", "red", "green")) +
    scale_alpha_manual(values = c(1, 0)) +
    guides(alpha = guide_legend(override.aes = list(shape = 21, fill = c("black", NA), alpha = c(1,1))))