在ggplot散点图中将不同变量的多个因子水平设置为相同颜色的简洁方法
Succinct way to set multiple factor levels of different variables to same color in ggplot scatterplots
考虑以下简化的数据框:
x = c(.35, .35, .37, .5, .55, .56, .9, .91, .89)
y = c(.35, .36, .35, .22, .27, .25, .88, .9, .87)
clu3 = as.factor(c(31,31,31,32,32,32,33,33,33))
clu4 = as.factor(c(41,41,41,42,43,43,44,44,44))
df = data.frame (x,y,clu3,clu4)
在我的分析中,三个聚类首先适合数据集(clu3,其因子水平为 31、32 和 33)。然后四个集群也适合数据集(clu4,其因子水平为 41、42、43、44),然后是五个集群和六个集群,依此类推。为简单起见,我只包含了拟合三个和四个聚类的结果。
我可以使用以下方法绘制每个“运行”(即三簇 运行 和四簇 运行)的结果:
ggplot(df, aes(x=x, y=y, color=clu3)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Three-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5))
ggplot(df, aes(x=x, y=y, color=clu4)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Four-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5))
现在,我正在 ggplot 中指定簇颜色。但在我的示例中,集群 31 和 41 是相同的(但来自不同的“运行s”),集群 33 和 44 也是相同的。在后面的 运行 中也有额外的相同集群(当将五个集群拟合到数据时,六个,等等)。我想做的是以简洁的方式指定不同变量(在本例中为 clu3 和 clu4)的因子水平的颜色。从感知上讲,它应该是这样的:
"31" | "41" = "purple"
"33" | "44" = "green"
"32" = "blue"
"42" = "orange"
"43" = "yellow"
我猜解决方案涉及 scale_fill_manual,并且我已经阅读了使因子水平颜色在绘图中保持一致的方法(即使未使用某些因子水平)。但在所有这些示例中,因子水平都是 相同的 变量,而我想使 来自不同变量的不同因子水平一致的颜色 。非常感谢任何建议!
注意:此解决方案适用于示例数据中的双集群情况。您将需要使用不同的逻辑(first/last 除外)为 > 2 个集群创建 new_clu
。
一种解决方案是将数据转换为“长”形式,按x
和y
分组,然后根据[=17]的值创建一个新变量new_clu
=] 和 clu4
.
注意:我使用的是 gather
,但您可以使用较新的 pivot_longer
。不相同的属性会产生警告,可以忽略。
df %>%
gather(Cluster, Val, 3:4) %>%
group_by(x, y) %>%
mutate(new_clu = case_when(
first(Val) == 31 & last(Val) == 41 ~ paste0(first(Val), "/", last(Val)),
first(Val) == 33 & last(Val) == 44 ~ paste0(first(Val), "/", last(Val)),
TRUE ~ Val
)
)
结果:
# A tibble: 18 x 5
# Groups: x, y [9]
x y Cluster Val new_clu
<dbl> <dbl> <chr> <chr> <chr>
1 0.35 0.35 clu3 31 31/41
2 0.35 0.36 clu3 31 31/41
3 0.37 0.35 clu3 31 31/41
4 0.5 0.22 clu3 32 32
5 0.55 0.27 clu3 32 32
6 0.56 0.25 clu3 32 32
7 0.9 0.88 clu3 33 33/44
8 0.91 0.9 clu3 33 33/44
9 0.89 0.87 clu3 33 33/44
10 0.35 0.35 clu4 41 31/41
11 0.35 0.36 clu4 41 31/41
12 0.37 0.35 clu4 41 31/41
13 0.5 0.22 clu4 42 42
14 0.55 0.27 clu4 43 43
15 0.56 0.25 clu4 43 43
16 0.9 0.88 clu4 44 33/44
17 0.91 0.9 clu4 44 33/44
18 0.89 0.87 clu4 44 33/44
现在您可以将其传递给 ggplot
并在 new_clu
上着色:
df %>%
gather(Cluster, Val, 3:4) %>%
group_by(x, y) %>%
mutate(new_clu = case_when(
first(Val) == 31 & last(Val) == 41 ~ paste0(first(Val), "/", last(Val)),
first(Val) == 33 & last(Val) == 44 ~ paste0(first(Val), "/", last(Val)),
TRUE ~ Val
)
) %>%
ggplot(aes(x, y)) +
geom_point(aes(color = new_clu))
结果:
正如您所建议的,使用 scale_fill_manual
或 scale_color_manual
是一个有效的选项。
您可以编写一个函数来匹配两个聚类之间的颜色(例如,相对于第一个或先前聚类的聚类)。
这是一种匹配颜色并将其按顺序应用于多个群集的方法:
library(ggplot2)
x <- c(.35, .35, .37, .5, .55, .56, .9, .91, .89)
y <- c(.35, .36, .35, .22, .27, .25, .88, .9, .87)
clu3 <- factor(c(31, 31, 31, 32, 32, 32, 33, 33, 33))
clu4 <- factor(c(41, 41, 41, 42, 43, 43, 44, 44, 44))
clu5 <- factor(c(51, 51, 52, 53, 54, 54, 55, 55, 55)) # added a few more clusters
clu6 <- factor(c(61, 61, 62, 63, 64, 64, 65, 66, 65))
df <- data.frame(x, y, clu3, clu4, clu5, clu6)
## assign specific colors to matching clusters; rest: use same colors
matchCol <- function(fac1, fac2, pal=c("#999999", "#E69F00", "#56B4E9",
"#009E73", "#F0E442", "#0072B2",
"#D55E00", "#CC79A7")){
maxl <- max(length(levels(fac1)), length(levels(fac2)))
if(length(pal) < maxl) { # make sure you have enough colors
warning("Not enough colors; using scales::hue_pal")
pal <- scales::hue_pal()(maxl)
}
tab <- as.matrix(table(fac1, fac2)) > 0
rs1 <- which(rowSums(tab) == 1)
rs2 <- apply(tab[rs1, , drop=FALSE], 1, which.max)
f1 <- setNames(pal[seq_along(levels(fac1))], levels(fac1))
f2 <- setNames(NA[seq_along(levels(fac2))], levels(fac2))
f2[levels(fac2)[rs2]] <- f1[levels(fac1)[rs1]] # add matching colors
f2n <- names(f2)
if(!identical(fac1, fac2)) f2n[rs2] <- paste0(levels(fac1)[rs1], " | ", levels(fac2)[rs2])
f2[is.na(f2)] <- setdiff(pal, f2)[seq_along(f2[is.na(f2)])] # fill in remaining colors
list(fac1=f1, fac2=f2, f2n=f2n ) # you only need f2 here, so could simplify
}
# then plot using matchCol function, e.g.:
ggplot(df, aes(x=x, y=y, color=clu4)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Four-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=matchCol(clu3, clu4)$fac2,
labels=matchCol(clu3, clu4)$f2)
# or generalized
clusts <- grep("clu", colnames(df), value=TRUE)
p1 <- lapply(clusts, function(z){
mc <- matchCol(get(clusts[1]), get(z))
ggplot(df, aes_string(x="x", y="y", color=z)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste0(gsub("clu", "", z),"-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=mc$fac2, labels=mc$f2)
}
)
cowplot::plot_grid(plotlist = p1)
# same, relative to previous clustering:
p2 <- lapply(seq_along(clusts), function(z){
mc <- matchCol(get(clusts[max(1, z-1)]), get(clusts[z]))
ggplot(df, aes_string(x="x", y="y", color=clusts[z])) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste0(gsub("clu", "", clusts[z]),"-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=mc$fac2, labels=mc$f2)
}
)
cowplot::plot_grid(plotlist = p2)
由 reprex package (v0.3.0)
于 2020-12-17 创建
考虑以下简化的数据框:
x = c(.35, .35, .37, .5, .55, .56, .9, .91, .89)
y = c(.35, .36, .35, .22, .27, .25, .88, .9, .87)
clu3 = as.factor(c(31,31,31,32,32,32,33,33,33))
clu4 = as.factor(c(41,41,41,42,43,43,44,44,44))
df = data.frame (x,y,clu3,clu4)
在我的分析中,三个聚类首先适合数据集(clu3,其因子水平为 31、32 和 33)。然后四个集群也适合数据集(clu4,其因子水平为 41、42、43、44),然后是五个集群和六个集群,依此类推。为简单起见,我只包含了拟合三个和四个聚类的结果。
我可以使用以下方法绘制每个“运行”(即三簇 运行 和四簇 运行)的结果:
ggplot(df, aes(x=x, y=y, color=clu3)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Three-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5))
ggplot(df, aes(x=x, y=y, color=clu4)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Four-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5))
现在,我正在 ggplot 中指定簇颜色。但在我的示例中,集群 31 和 41 是相同的(但来自不同的“运行s”),集群 33 和 44 也是相同的。在后面的 运行 中也有额外的相同集群(当将五个集群拟合到数据时,六个,等等)。我想做的是以简洁的方式指定不同变量(在本例中为 clu3 和 clu4)的因子水平的颜色。从感知上讲,它应该是这样的:
"31" | "41" = "purple"
"33" | "44" = "green"
"32" = "blue"
"42" = "orange"
"43" = "yellow"
我猜解决方案涉及 scale_fill_manual,并且我已经阅读了使因子水平颜色在绘图中保持一致的方法(即使未使用某些因子水平)。但在所有这些示例中,因子水平都是 相同的 变量,而我想使 来自不同变量的不同因子水平一致的颜色 。非常感谢任何建议!
注意:此解决方案适用于示例数据中的双集群情况。您将需要使用不同的逻辑(first/last 除外)为 > 2 个集群创建 new_clu
。
一种解决方案是将数据转换为“长”形式,按x
和y
分组,然后根据[=17]的值创建一个新变量new_clu
=] 和 clu4
.
注意:我使用的是 gather
,但您可以使用较新的 pivot_longer
。不相同的属性会产生警告,可以忽略。
df %>%
gather(Cluster, Val, 3:4) %>%
group_by(x, y) %>%
mutate(new_clu = case_when(
first(Val) == 31 & last(Val) == 41 ~ paste0(first(Val), "/", last(Val)),
first(Val) == 33 & last(Val) == 44 ~ paste0(first(Val), "/", last(Val)),
TRUE ~ Val
)
)
结果:
# A tibble: 18 x 5
# Groups: x, y [9]
x y Cluster Val new_clu
<dbl> <dbl> <chr> <chr> <chr>
1 0.35 0.35 clu3 31 31/41
2 0.35 0.36 clu3 31 31/41
3 0.37 0.35 clu3 31 31/41
4 0.5 0.22 clu3 32 32
5 0.55 0.27 clu3 32 32
6 0.56 0.25 clu3 32 32
7 0.9 0.88 clu3 33 33/44
8 0.91 0.9 clu3 33 33/44
9 0.89 0.87 clu3 33 33/44
10 0.35 0.35 clu4 41 31/41
11 0.35 0.36 clu4 41 31/41
12 0.37 0.35 clu4 41 31/41
13 0.5 0.22 clu4 42 42
14 0.55 0.27 clu4 43 43
15 0.56 0.25 clu4 43 43
16 0.9 0.88 clu4 44 33/44
17 0.91 0.9 clu4 44 33/44
18 0.89 0.87 clu4 44 33/44
现在您可以将其传递给 ggplot
并在 new_clu
上着色:
df %>%
gather(Cluster, Val, 3:4) %>%
group_by(x, y) %>%
mutate(new_clu = case_when(
first(Val) == 31 & last(Val) == 41 ~ paste0(first(Val), "/", last(Val)),
first(Val) == 33 & last(Val) == 44 ~ paste0(first(Val), "/", last(Val)),
TRUE ~ Val
)
) %>%
ggplot(aes(x, y)) +
geom_point(aes(color = new_clu))
结果:
正如您所建议的,使用 scale_fill_manual
或 scale_color_manual
是一个有效的选项。
您可以编写一个函数来匹配两个聚类之间的颜色(例如,相对于第一个或先前聚类的聚类)。
这是一种匹配颜色并将其按顺序应用于多个群集的方法:
library(ggplot2)
x <- c(.35, .35, .37, .5, .55, .56, .9, .91, .89)
y <- c(.35, .36, .35, .22, .27, .25, .88, .9, .87)
clu3 <- factor(c(31, 31, 31, 32, 32, 32, 33, 33, 33))
clu4 <- factor(c(41, 41, 41, 42, 43, 43, 44, 44, 44))
clu5 <- factor(c(51, 51, 52, 53, 54, 54, 55, 55, 55)) # added a few more clusters
clu6 <- factor(c(61, 61, 62, 63, 64, 64, 65, 66, 65))
df <- data.frame(x, y, clu3, clu4, clu5, clu6)
## assign specific colors to matching clusters; rest: use same colors
matchCol <- function(fac1, fac2, pal=c("#999999", "#E69F00", "#56B4E9",
"#009E73", "#F0E442", "#0072B2",
"#D55E00", "#CC79A7")){
maxl <- max(length(levels(fac1)), length(levels(fac2)))
if(length(pal) < maxl) { # make sure you have enough colors
warning("Not enough colors; using scales::hue_pal")
pal <- scales::hue_pal()(maxl)
}
tab <- as.matrix(table(fac1, fac2)) > 0
rs1 <- which(rowSums(tab) == 1)
rs2 <- apply(tab[rs1, , drop=FALSE], 1, which.max)
f1 <- setNames(pal[seq_along(levels(fac1))], levels(fac1))
f2 <- setNames(NA[seq_along(levels(fac2))], levels(fac2))
f2[levels(fac2)[rs2]] <- f1[levels(fac1)[rs1]] # add matching colors
f2n <- names(f2)
if(!identical(fac1, fac2)) f2n[rs2] <- paste0(levels(fac1)[rs1], " | ", levels(fac2)[rs2])
f2[is.na(f2)] <- setdiff(pal, f2)[seq_along(f2[is.na(f2)])] # fill in remaining colors
list(fac1=f1, fac2=f2, f2n=f2n ) # you only need f2 here, so could simplify
}
# then plot using matchCol function, e.g.:
ggplot(df, aes(x=x, y=y, color=clu4)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste("Four-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=matchCol(clu3, clu4)$fac2,
labels=matchCol(clu3, clu4)$f2)
# or generalized
clusts <- grep("clu", colnames(df), value=TRUE)
p1 <- lapply(clusts, function(z){
mc <- matchCol(get(clusts[1]), get(z))
ggplot(df, aes_string(x="x", y="y", color=z)) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste0(gsub("clu", "", z),"-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=mc$fac2, labels=mc$f2)
}
)
cowplot::plot_grid(plotlist = p1)
# same, relative to previous clustering:
p2 <- lapply(seq_along(clusts), function(z){
mc <- matchCol(get(clusts[max(1, z-1)]), get(clusts[z]))
ggplot(df, aes_string(x="x", y="y", color=clusts[z])) +
geom_point(size=4)+
theme_bw()+
ggtitle(paste0(gsub("clu", "", clusts[z]),"-cluster scatterplot"))+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=mc$fac2, labels=mc$f2)
}
)
cowplot::plot_grid(plotlist = p2)
由 reprex package (v0.3.0)
于 2020-12-17 创建