我使用了以下 ggplot
命令:
ggplot(survey, aes(x = age)) + stat_bin(aes(n = nrow(h3), y = ..count.. / n), binwidth = 10)
+ scale_y_continuous(formatter = "percent", breaks = c(0, 0.1, 0.2))
+ facet_grid(hospital ~ .)
+ theme(panel.background = theme_blank())
生产
https://imgur.com/lXK7C.png
但是,我想将 facet 标签更改为更短的标签(例如 Hosp 1
、Hosp 2
...),因为它们现在太长而且看起来很拥挤(增加graph 不是一个选项,它会在文档中占用太多空间)。我查看了 facet_grid 帮助页面,但不知道如何操作。
这是避免编辑数据的解决方案:
假设您的绘图由数据框的 group
部分分面,该部分具有级别 control, test1, test2
,然后创建一个由这些值命名的列表:
hospital_names <- list(
'Hospital#1'="Some Hospital",
'Hospital#2'="Another Hospital",
'Hospital#3'="Hospital Number 3",
'Hospital#4'="The Other Hospital"
)
然后创建一个 'labeller' 函数,并将其推送到您的 facet_grid 调用中:
hospital_labeller <- function(variable,value){
return(hospital_names[value])
}
ggplot(survey,aes(x=age)) + stat_bin(aes(n=nrow(h3),y=..count../n), binwidth=10)
+ facet_grid(hospital ~ ., labeller=hospital_labeller)
...
这使用数据框的级别来索引医院名称列表,返回列表值(正确的名称)。
请注意,这仅在您只有一个刻面变量时才有效。如果您有两个方面,那么您的标注器函数需要为每个方面返回不同的名称向量。你可以这样做:
plot_labeller <- function(variable,value){
if (variable=='facet1') {
return(facet1_names[value])
} else {
return(facet2_names[value])
}
}
其中 facet1_names
和 facet2_names
是由方面索引名称(“Hostpital#1”等)索引的名称的预定义列表。
编辑:如果您传递贴标机不知道的变量/值组合,上述方法将失败。您可以为未知变量添加故障保护,如下所示:
plot_labeller <- function(variable,value){
if (variable=='facet1') {
return(facet1_names[value])
} else if (variable=='facet2') {
return(facet2_names[value])
} else {
return(as.character(value))
}
}
答案改编自 how to change strip.text labels in ggplot with facet and margin=TRUE
编辑:警告:如果您使用此方法按 character 列进行分面,您可能会得到不正确的标签。请参阅 this bug report。 在 ggplot2 的最新版本中已修复。
这是另一个与@naught101 给出的精神相一致的解决方案,但更简单,并且不会对最新版本的 ggplot2 发出警告。
基本上,您首先创建一个命名字符向量
hospital_names <- c(
`Hospital#1` = "Some Hospital",
`Hospital#2` = "Another Hospital",
`Hospital#3` = "Hospital Number 3",
`Hospital#4` = "The Other Hospital"
)
然后你将它用作贴标机,只需将@naught101 给出的代码的最后一行修改为
... + facet_grid(hospital ~ ., labeller = as_labeller(hospital_names))
希望这可以帮助。
as_labeller
中?我在 CRAN GitHub repository 上找到了一些源代码,但升级到最新版本后(在 CRAN 上!)我似乎没有该功能。
hospital ~ gender
之类的?有没有办法在两个轴上使用贴标机?我在文档中看不到任何明显的东西。
使用以下内容更改基础因子级别名称:
# Using the Iris data
> i <- iris
> levels(i$Species)
[1] "setosa" "versicolor" "virginica"
> levels(i$Species) <- c("S", "Ve", "Vi")
> ggplot(i, aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm)))
),它将不会出现在数学表达式中。如何将表达式显示为方面标签?
以下是我使用 ggplot2 版本 2.2.1 处理 facet_grid(yfacet~xfacet)
的方法:
facet_grid(
yfacet~xfacet,
labeller = labeller(
yfacet = c(`0` = "an y label", `1` = "another y label"),
xfacet = c(`10` = "an x label", `20` = "another x label")
)
)
请注意,这不包含对 as_labeller()
的调用——我曾为此苦苦挣扎了一段时间。
这种方法的灵感来自帮助页面 Coerce to labeller function 上的最后一个示例。
setNames()
stackoverflow.com/a/22428439/3362993 构造这些命名向量
在不修改基础数据的情况下进行更改的最简单方法是:
使用 as_labeller() 创建一个对象。如果列名以数字开头或包含空格或特殊字符,请不要忘记使用反引号:
# Necessary to put RH% into the facet labels
hum_names <- as_labeller(
c(`50` = "RH% 50", `60` = "RH% 60",`70` = "RH% 70",
`80` = "RH% 80",`90` = "RH% 90", `100` = "RH% 100"))
添加到ggplot:
ggplot(dataframe, aes(x = Temperature.C, y = fit)) +
geom_line() +
facet_wrap(~Humidity.RH., nrow = 2, labeller = hum_names)
labeller = labeller(Type = c(...), Humidity = c(...))
其中 ... 是键值对
RH%
,一个更强大的解决方案是用 hum_names <- as_labeller(function(x) paste('RH%', x))
替换此答案中的第 1 步
如果您有两个方面 hospital
和 room
但只想重命名一个,您可以使用:
facet_grid( hospital ~ room, labeller = labeller(hospital = as_labeller(hospital_names)))
要使用基于向量的方法重命名两个方面(如 naught101 的答案),您可以执行以下操作:
facet_grid( hospital ~ room, labeller = labeller(hospital = as_labeller(hospital_names),
room = as_labeller(room_names)))
添加另一个类似于@domi 的解决方案,解析数学符号、上标、下标、括号/括号等。
library(tidyverse)
theme_set(theme_bw(base_size = 18))
### create separate name vectors
# run `demo(plotmath)` for more examples of mathematical annotation in R
am_names <- c(
`0` = "delta^{15}*N-NO[3]^-{}",
`1` = "sqrt(x,y)"
)
# use `scriptstyle` to reduce the size of the parentheses &
# `bgroup` to make adding `)` possible
cyl_names <- c(
`4` = 'scriptstyle(bgroup("", a, ")"))~T~-~5*"%"',
`6` = 'scriptstyle(bgroup("", b, ")"))~T~+~10~degree*C',
`8` = 'scriptstyle(bgroup("", c, ")"))~T~+~30*"%"'
)
ggplot(mtcars, aes(wt, mpg)) +
geom_jitter() +
facet_grid(am ~ cyl,
labeller = labeller(am = as_labeller(am_names, label_parsed),
cyl = as_labeller(cyl_names, label_parsed))
) +
geom_text(x = 4, y = 25, size = 4, nudge_y = 1,
parse = TRUE, check_overlap = TRUE,
label = as.character(expression(paste("Log"["10"], bgroup("(", frac("x", "y"), ")")))))
https://i.imgur.com/ccGQ9Yv.png
### OR create new variables then assign labels directly
# reverse facet orders just for fun
mtcars <- mtcars %>%
mutate(am2 = factor(am, labels = am_names),
cyl2 = factor(cyl, labels = rev(cyl_names), levels = rev(attr(cyl_names, "names")))
)
ggplot(mtcars, aes(wt, mpg)) +
geom_jitter() +
facet_grid(am2 ~ cyl2,
labeller = label_parsed) +
annotate("text", x = 4, y = 30, size = 5,
parse = TRUE,
label = as.character(expression(paste("speed [", m * s^{-1}, "]"))))
https://i.imgur.com/Jpvowh8.png
由 reprex package (v0.2.1.9000) 于 2019 年 3 月 30 日创建
简单的解决方案(来自 here):
p <- ggplot(mtcars, aes(disp, drat)) + geom_point()
# Example (old labels)
p + facet_wrap(~am)
to_string <- as_labeller(c(`0` = "Zero", `1` = "One"))
# Example (New labels)
p + facet_wrap(~am, labeller = to_string)
这个解决方案非常接近@domi,但旨在通过获取前 4 个字母和最后一个数字来缩短名称。
library(ggplot2)
# simulate some data
xy <- data.frame(hospital = rep(paste("Hospital #", 1:3, sep = ""), each = 30),
value = rnorm(90))
shortener <- function(string) {
abb <- substr(string, start = 1, stop = 4) # fetch only first 4 strings
num <- gsub("^.*(\\d{1})$", "\\1", string) # using regular expression, fetch last number
out <- paste(abb, num) # put everything together
out
}
ggplot(xy, aes(x = value)) +
theme_bw() +
geom_histogram() +
facet_grid(hospital ~ ., labeller = labeller(hospital = shortener))
https://i.stack.imgur.com/MttJJ.png
请注意,如果 ggplot 显示的因子少于您的变量实际包含的因子(例如,如果您进行了子集化,则可能会发生这种情况),此解决方案将无法正常工作:
library(ggplot2)
labeli <- function(variable, value){
names_li <- list("versicolor"="versi", "virginica"="virg")
return(names_li[value])
}
dat <- subset(iris,Species!="setosa")
ggplot(dat, aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ ., labeller=labeli)
一个简单的解决方案(除了在 names_li 中添加所有未使用的因子,这可能很乏味)是在原始数据集或 labbeler 函数中使用 droplevels() 删除未使用的因子,请参阅:
labeli2 <- function(variable, value){
value <- droplevels(value)
names_li <- list("versicolor"="versi", "virginica"="virg")
return(names_li[value])
}
dat <- subset(iris,Species!="setosa")
ggplot(dat, aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ ., labeller=labeli2)
facet_wrap
和 facet_grid
都接受来自 ifelse
的输入作为参数。因此,如果用于分面的变量是合乎逻辑的,则解决方案非常简单:
facet_wrap(~ifelse(variable, "Label if true", "Label if false"))
如果变量的类别较多,则 ifelse
语句需要为 nested。
作为副作用,这还允许在 ggplot
调用中分面创建组。
这对我有用。
定义一个因子:
hospitals.factor<- factor( c("H0","H1","H2") )
并在 ggplot()
中使用:
facet_grid( hospitals.factor[hospital] ~ . )
以 variable, value
作为参数的 labeller 函数定义对我不起作用。此外,如果你想使用表达式,你需要使用 lapply 并且不能简单地使用 arr[val]
,因为函数的参数是 data.frame。
这段代码确实有效:
libary(latex2exp)
library(ggplot2)
arr <- list('virginica'=TeX("x_1"), "versicolor"=TeX("x_2"), "setosa"=TeX("x_3"))
mylabel <- function(val) { return(lapply(val, function(x) arr[x])) }
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) + geom_line() + facet_wrap(~Species, labeller=mylabel)
由于我还不允许对帖子发表评论,因此我将其作为 Vince's answer 和 son520804's answer 的附录单独发布。功劳归于他们。
Son520804:使用 Iris 数据:我假设:您已经安装了 dplyr 包,其中包含方便的 mutate 命令,并且您的数据集名为调查。调查 %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) 此命令可帮助您重命名列,但保留所有其他列。然后做同样的 facet_wrap,你现在很好。
使用 Vince 的 iris 示例和 son520804 的部分代码,我使用 mutate 函数进行了此操作,并在不触及原始数据集的情况下实现了简单的解决方案。诀窍是创建一个替代名称向量并在管道内使用 mutate() 临时更正构面名称:
i <- iris
levels(i$Species)
[1] "setosa" "versicolor" "virginica"
new_names <- c(
rep("Bristle-pointed iris", 50),
rep("Poison flag iris",50),
rep("Virginia iris", 50))
i %>% mutate(Species=new_names) %>%
ggplot(aes(Petal.Length))+
stat_bin()+
facet_grid(Species ~ .)
在此示例中,您可以看到 i$Species 的级别临时更改为包含在 new_names 向量中的相应常用名称。包含的行
mutate(Species=new_names) %>%
可以很容易地删除以显示原始命名。
注意事项:如果未正确设置 new_name 向量,这可能很容易在名称中引入错误。使用单独的函数来替换变量字符串可能会更干净。请记住,可能需要以不同的方式重复 new_name 向量以匹配原始数据集的顺序。请双重和三重检查这是否正确实现。
new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris')
然后在 mutate 中您可以创建一个新列:mutate(Spec = new_names[Species])
只是扩展 naught101 的答案——归功于他
plot_labeller <- function(variable,value, facetVar1='<name-of-1st-facetting-var>', var1NamesMapping=<pass-list-of-name-mappings-here>, facetVar2='', var2NamesMapping=list() )
{
#print (variable)
#print (value)
if (variable==facetVar1)
{
value <- as.character(value)
return(var1NamesMapping[value])
}
else if (variable==facetVar2)
{
value <- as.character(value)
return(var2NamesMapping[value])
}
else
{
return(as.character(value))
}
}
您需要做的是创建一个名称到名称映射的列表
clusteringDistance_names <- list(
'100'="100",
'200'="200",
'300'="300",
'400'="400",
'600'="500"
)
并使用新的默认参数重新定义 plot_labeller()
:
plot_labeller <- function(variable,value, facetVar1='clusteringDistance', var1NamesMapping=clusteringDistance_names, facetVar2='', var1NamesMapping=list() )
接着:
ggplot() +
facet_grid(clusteringDistance ~ . , labeller=plot_labeller)
或者,您可以为您想要的每个标签更改创建一个专用函数。
我有另一种方法可以在不更改基础数据的情况下实现相同的目标:
ggplot(transform(survey, survey = factor(survey,
labels = c("Hosp 1", "Hosp 2", "Hosp 3", "Hosp 4"))), aes(x = age)) +
stat_bin(aes(n = nrow(h3),y=..count../n), binwidth = 10) +
scale_y_continuous(formatter = "percent", breaks = c(0, 0.1, 0.2)) +
facet_grid(hospital ~ .) +
opts(panel.background = theme_blank())
我上面所做的是更改原始数据框中因子的标签,这是与原始代码相比的唯一区别。
我认为所有其他解决方案都非常有助于做到这一点,但还有另一种方法。
我假设:
你已经安装了 dplyr 包,它有方便的 mutate 命令,并且
您的数据集名为调查。调查 %>% 变异(Hosp1 = Hospital1,Hosp2 = Hospital2,........)
此命令可帮助您重命名列,但保留所有其他列。
然后做同样的facet_wrap
,你现在很好。
case_when()
的 mutate()
?不知道为什么这被赞成,因为它肯定行不通。
我觉得我应该为此添加答案,因为我花了很长时间才完成这项工作:
如果出现以下情况,此答案适合您:
您不想编辑原始数据
如果您需要标签中的表达式(bquote)和
如果你想要一个单独的标签名称向量的灵活性
我基本上将标签放在命名向量中,这样标签就不会混淆或切换。 labeller
表达式可能更简单,但这至少有效(非常欢迎改进)。注意 `(反引号)以保护方面因素。
n <- 10
x <- seq(0, 300, length.out = n)
# I have my data in a "long" format
my_data <- data.frame(
Type = as.factor(c(rep('dl/l', n), rep('alpha', n))),
T = c(x, x),
Value = c(x*0.1, sqrt(x))
)
# the label names as a named vector
type_names <- c(
`nonsense` = "this is just here because it looks good",
`dl/l` = Linear~Expansion~~Delta*L/L[Ref]~"="~"[%]", # bquote expression
`alpha` = Linear~Expansion~Coefficient~~alpha~"="~"[1/K]"
)
ggplot() +
geom_point(data = my_data, mapping = aes(T, Value)) +
facet_wrap(. ~ Type, scales="free_y",
labeller = label_bquote(.(as.expression(
eval(parse(text = paste0('type_names', '$`', Type, '`')))
)))) +
labs(x="Temperature [K]", y="", colour = "") +
theme(legend.position = 'none')
https://i.stack.imgur.com/ZAGeQ.png
您是否尝试过更改 Hospital
向量的特定级别?
levels(survey$hospital)[levels(survey$hospital) == "Hospital #1"] <- "Hosp 1"
levels(survey$hospital)[levels(survey$hospital) == "Hospital #2"] <- "Hosp 2"
levels(survey$hospital)[levels(survey$hospital) == "Hospital #3"] <- "Hosp 3"
来自 mishabalyasin 的单线:
facet_grid(.~vs, labeller = purrr::partial(label_both, sep = " #"))
看到它在行动
library(reprex)
library(tidyverse)
mtcars %>%
ggplot(aes(x="", y=gear,fill=factor(gear), group=am)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +
facet_grid(.~vs, labeller = purrr::partial(label_both, sep = " #"))
https://i.imgur.com/KxEaEm2.png
由 reprex package (v2.0.0) 于 2021 年 7 月 9 日创建
这些天我解决这个问题的方法是使用 dplyr::case_when
在 facet_grid
或 facet_wrap
函数中生成标签器。这是@lillemets 提出的解决方案的扩展
ggplot(survey, aes(x = age)) + stat_bin(aes(n = nrow(h3), y = ..count.. / n), binwidth = 10)
+ scale_y_continuous(formatter = "percent", breaks = c(0, 0.1, 0.2))
+ facet_grid(case_when(hospital == "Hospital #1" ~ "Hosp1",
hospital == "Hospital #2" ~ "Hosp2") ~ .)
+ theme(panel.background = theme_blank())
很好的是,如果您有第二个方面标签要更改,您只需在 facet_grid
内 ~
的另一侧使用相同的方法
经过一段时间的努力,我发现我们可以结合使用 forcats
中的 fct_relevel()
和 fct_recode()
来更改构面的顺序以及修复构面标签。我不确定它是否受设计支持,但它有效!看看下面的图:
library(tidyverse)
before <- mpg %>%
ggplot(aes(displ, hwy)) +
geom_point() +
facet_wrap(~class)
before
https://i.imgur.com/AEB5g9p.png
after <- mpg %>%
ggplot(aes(displ, hwy)) +
geom_point() +
facet_wrap(
vars(
# Change factor level name
fct_recode(class, "motorbike" = "2seater") %>%
# Change factor level order
fct_relevel("compact")
)
)
after
https://i.imgur.com/8ZO8PWN.png
由 reprex package (v0.3.0) 于 2020 年 2 月 16 日创建