269

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

生产

替代文字

但是,我想将构面标签更改为更短的内容(例如Hosp 1Hosp 2...),因为它们现在太长并且看起来局促(增加图形的高度不是一种选择,它会占用太多空间文件)。我查看了facet_grid帮助页面,但无法弄清楚如何。

4

22 回答 22

315

这是避免编辑数据的解决方案:

假设你的情节是由group你的数据框部分组成的,它有 levels 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_namesfacet2_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))
  }
}

答案改编自如何使用 facet 和 margin=TRUE 更改 ggplot 中的 strip.text 标签


编辑:警告:如果您使用此方法按字符列分面,您可能会得到不正确的标签。请参阅此错误报告在最新版本的 ggplot2 中修复。

于 2012-08-24T06:28:32.867 回答
256

这是另一个与@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))

希望这可以帮助。

于 2016-01-15T12:26:09.753 回答
140

使用以下内容更改基础因子级别名称:

# 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 ~ .)
于 2010-08-13T01:40:03.953 回答
37

以下是我facet_grid(yfacet~xfacet)使用 ggplot2 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()- 我挣扎了一段时间的调用。

这种方法的灵感来自帮助页面Coerce to labeller function上的最后一个示例。

于 2017-03-20T20:13:42.867 回答
36

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

  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)
于 2019-02-26T17:44:20.287 回答
26

如果您有两个方面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)))
于 2016-06-12T20:44:12.223 回答
15

添加另一个类似于@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"), ")")))))

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

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

于 2019-03-31T06:45:08.457 回答
14

简单的解决方案(从这里):

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)
于 2020-04-29T11:42:32.120 回答
10

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

在此处输入图像描述

于 2018-09-23T10:38:41.743 回答
9

请注意,如果 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)
于 2013-06-11T09:42:24.513 回答
9

两者都facet_wrap接受facet_grid输入ifelse作为参数。因此,如果用于分面的变量是合乎逻辑的,则解决方案非常简单:

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

如果变量的类别较多,则ifelse语句需要嵌套

作为副作用,这还允许在ggplot呼叫中对组的创建进行分面。

于 2017-11-08T09:56:01.110 回答
4

这对我有用。

定义一个因子:

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

并使用,在ggplot()

facet_grid( hospitals.factor[hospital] ~ . )
于 2018-12-16T14:48:59.073 回答
3

带有 as 参数的 labeller 函数定义variable, value对我不起作用。此外,如果你想使用表达式,你需要使用 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)
于 2018-08-04T14:59:25.470 回答
3

由于我还不允许对帖子发表评论,因此我将其单独发布为Vince 的答案son520804 的答案的附录。功劳归于他们。

儿子520804:

使用虹膜数据:

我假设:
您已经安装了 dplyr 包,其中包含方便的 mutate 命令,并且您的数据集名为调查。 survey %>% 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 向量以匹配原始数据集的顺序。请双重和三重检查这是否正确实现。

于 2018-08-21T12:18:26.710 回答
2

只是扩展 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) 

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

于 2015-06-17T14:05:12.703 回答
2

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

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

我上面所做的是更改原始数据框中因子的标签,这是与原始代码相比的唯一区别。

于 2017-03-10T03:49:22.433 回答
2

我认为所有其他解决方案都非常有助于做到这一点,但还有另一种方法。

我假设:

  • 您已经安装了dplyr包含方便mutate命令的软件包,并且
  • 您的数据集名为survey.

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

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

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

于 2017-12-19T23:33:33.487 回答
2

我觉得我应该为此添加答案,因为我花了很长时间才完成这项工作:

如果出现以下情况,此答案适合您:

  • 不想编辑原始数据
  • 如果您需要标签中的表达式( ) 和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')

在此处输入图像描述

于 2019-10-09T15:38:30.717 回答
1

您是否尝试过更改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"
于 2018-04-28T06:48:28.927 回答
1

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

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

于 2021-07-09T07:25:38.083 回答
0

经过一段时间的努力,我发现我们可以结合使用fct_relevel()fct_recode()fromforcats来改变 facet 的顺序以及修复 facet 标签。我不确定它是否受设计支持,但它有效!看看下面的图:

library(tidyverse)

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

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

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

于 2020-02-16T08:35:26.977 回答
0

这些天我解决这个问题的方法是使用在or函数dplyr::case_when中生成标签器。这是@lillemets 提出的解决方案的扩展facet_gridfacet_wrap

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

于 2022-01-30T04:21:15.710 回答