如何更改facet标签?

我使用了以下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())

生产

alt text

然而,我想将方面标签更改为更短的标签(如Hosp 1Hosp 2…),因为它们现在太长了,看起来局促(增加图形的高度不是一个选项,它将占用文档中的太多空间)。我看了facet_grid帮助页,但不知道怎么做。

360069 次浏览

更改底层因子级别的名称,如下所示:

# 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 ~ .)

这里有一个避免编辑数据的解决方案:

假设你的图是由你的数据帧的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)
...

它使用数据帧的级别来索引hospital_names列表,并返回列表值(正确的名称)。


请注意,这仅适用于只有一个facet变量的情况。如果您有两个facet,那么您的labeller函数需要为每个facet返回不同的name向量。你可以这样做:

plot_labeller <- function(variable,value){
if (variable=='facet1') {
return(facet1_names[value])
} else {
return(facet2_names[value])
}
}

其中facet1_namesfacet2_names是由facet索引名('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))
}
}

答自如何更换板条。ggplot中带有facet和margin=TRUE的文本标签


在ggplot2的最新版本中修复了edit: WARNING:如果您使用此方法对字符列进行facet,您可能会得到不正确的标签。见此错误报告.;

注意,这个解决方案不会很好地工作,如果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中添加所有未使用的因子,这可能很乏味)是使用droplevels()删除未使用的因子,要么在原始数据集中,要么在labbeler函数中,参见:

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)

只是延续了"淘气101 "的答案,功劳归他

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)

或者,您可以为您想要的每个标签更改创建一个专用函数。

下面是另一个解决方案,它遵循@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))

希望这能有所帮助。

如果你有两个facet hospitalroom,但只想重命名其中一个,你可以使用:

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)))

我有另一种方法可以在不改变底层数据的情况下实现相同的目标:

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())

我上面所做的是改变原始数据帧中因子的标签,这是与原始代码相比的唯一不同之处。

下面是我如何使用ggplot2对facet_grid(yfacet~xfacet)做的,版本2.2.1:

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()的调用——这是我在一段时间内难以解决的问题。

这个方法的灵感来自于帮助页强制到标签函数上的最后一个例子。

facet_wrapfacet_grid也接受来自ifelse的输入作为参数。因此,如果用于刻面的变量是合乎逻辑的,解决方案非常简单:

facet_wrap(~ifelse(variable, "Label if true", "Label if false"))

如果变量有更多类别,ifelse语句需要是嵌套的

作为一个副作用,这也允许在ggplot调用中创建组。

我认为所有其他解决方案都非常有用,但还有另一种方法。

我认为:

  • 你已经安装了dplyr包,它有方便的mutate命令
  • 你的数据集被命名为survey

    < p >调查% > % 变异(Hosp1 = Hospital1 Hosp2 = Hospital2 ,........) < / >

此命令帮助您重命名列,但保留所有其他列。

然后做同样的facet_wrap,你现在很好。

你试过改变你的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"

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)

由于我还不允许评论帖子,所以我将其作为文斯的回答son520804的回答的附录单独发布。功劳归于他们。

Son520804:

使用虹膜数据:

< p >我认为:< br > 您已经安装了dplyr包,其中有方便的mutate命令 您的数据集名为survey。 survey %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) 此命令帮助您重命名列,但保留所有其他列。 然后做同样的facet_wrap,你现在没事了
使用Vince的虹膜示例和son520804的部分代码,我用突变函数做到了这一点,并且在不接触原始数据集的情况下实现了一个简单的解决方案。 诀窍是创建一个替代名称向量,并在管道中使用mutate()临时更正facet名称:

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向量可能需要以不同的方式重复,以匹配原始数据集的顺序。请再三检查这是否正确实现。

这个解决方案非常接近于@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))

enter image description here

这对我很有用。

定义一个因素:

hospitals.factor<- factor( c("H0","H1","H2") )

和使用,在ggplot():

facet_grid( hospitals.factor[hospital] ~ . )

在不修改底层数据的情况下进行更改的最简单方法是:

  1. 使用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"))
  1. 在ggplot中添加:
    ggplot(dataframe, aes(x = Temperature.C, y = fit)) +
geom_line() +
facet_wrap(~Humidity.RH., nrow = 2, labeller = hum_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"), ")")))))

< img src = " https://i.imgur.com/ccGQ9Yv.png " alt = " " >

### 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}, "]"))))

< img src = " https://i.imgur.com/Jpvowh8.png " alt = " " >

reprex包 (v0.2.1.9000)于2019-03-30创建

我觉得我应该加上我的答案,因为我花了很长时间才做到这一点:

这个答案是为你准备的:

  • 你做想编辑你的原始数据
  • 如果你的标签中需要表达式 (bquote)
  • 如果你想要一个单独的标签name-vector的灵活性

我基本上把标签放在一个命名向量中,这样标签就不会混淆或切换。labeller表达式可能更简单,但这至少是可行的(非常欢迎改进)。注意'(后引号)以保护facet-factor。

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')

enter image description here

在挣扎了一段时间后,我发现我们可以结合使用fct_relevel()fct_recode() from forcats来改变facet的顺序以及固定facet标签。我不确定它是否被设计支持,但它确实有效!看看下面的图表:

library(tidyverse)


before <- mpg %>%
ggplot(aes(displ, hwy)) +
geom_point() +
facet_wrap(~class)
before

< img src = " https://i.imgur.com/AEB5g9p.png " alt = " " >

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

< img src = " https://i.imgur.com/8ZO8PWN.png " alt = " " >

reprex包 (v0.3.0)创建于2020-02-16

简单的解决方案(来自在这里):

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)

一个一行从< A href="https://community.rstudio.com/t/changing-sep-in-labeller/7369/2?u=samuel.saari" rel="nofollow noreferrer">mishabalyasin : < / p >

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 = " #"))

< img src = " https://i.imgur.com/KxEaEm2.png " alt = " / >

reprex包 (v2.0.0)创建于2021-07-09

我最近解决这个问题的方法是使用dplyr::case_whenfacet_gridfacet_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标签要更改,你只需在facet_grid中的~的另一侧使用相同的方法