首页 文章

ggplot:如何更改构面标签?

提问于
浏览
175

我使用了以下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 ~ .) 
  + opts(panel.background = theme_blank())

生产环境

alt text

我想将facet标签更改为更短的标签(如Hosp 1,Hosp 2 ......),因为它们现在太长并且看起来很狭窄(增加图形的高度不是一个选项,它需要文档中的空间太大) . 我查看了facet_grid帮助页面,但无法弄清楚如何 .

14 回答

  • 2

    我认为所有其他解决方案对此非常有帮助,但还有另一种方法 .

    我假设:

    • 你已经安装了 dplyr 包,它有方便的 mutate 命令,和

    • 您的数据集名为 survey .

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

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

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

  • 245

    如果你有两个方面 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)))
    
  • 5

    使用 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)
    
  • 100

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

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

    这是我用 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上的最后一个示例 .

  • 7

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

    或者,您可以为要拥有的每个标签更改创建专用功能 .

  • 18

    您是否尝试更改 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"
    
  • 1

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

  • 160

    因为我'm not yet allowed to comment on posts, I' m单独发布这个作为Vince's answerson520804's answer的附录 . 信用归他们所有 .

    Son520804:使用Iris数据:我假设:您已经安装了dplyr软件包,它具有方便的mutate命令,您的数据集名为survey . 调查%>%mutate(Hosp1 = Hospital1,Hosp2 = Hospital2,........)此命令可帮助您重命名列,但保留所有其他列 . 然后做同样的facet_wrap,你现在很好 .

    使用Vince的虹膜示例和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) %>%
    

    可以轻松删除以显示原始命名 .

    Word of caution: 如果未正确设置new_name向量,则可能很容易在名称中引入错误 . 使用单独的函数替换变量字符串可能会更清晰 . 请记住,new_name向量可能需要以不同的方式重复以匹配原始数据集的顺序 . 请双重检查这是否正确实现 .

  • 20

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

    假设您的绘图由数据框的 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"
    )
    

    然后创建一个'贴标机'功能,并将其推入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列表,返回列表值(正确的名称) .


    请注意,这仅适用于只有一个分面变量的情况 . 如果您有两个方面,那么您的贴标机功能需要为每个方面返回不同的名称向量 . 您可以使用以下内容执行此操作:

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

    其中 facet1_namesfacet2_names 是由构面索引名称('Hostpital#1'等)索引的预定义名称列表 .


    Edit: 如果传递标签程序不知道的变量/值组合,则上述方法将失败 . 您可以为未知变量添加故障保护,如下所示:

    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


    编辑:警告:如果您使用此方法按字符列进行构面,则可能是标签不正确 . 请参阅此错误报告 . 修复了最新版本的ggplot2 .

  • 4

    请注意,如果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)
    
  • 1

    这是另一个解决方案,它符合@ 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))
    

    希望这可以帮助 .

  • 0

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

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

    如果变量有更多类别,则 ifelse 语句必须为nested .

    作为副作用,这还允许在 ggplot 调用中创建要刻面的组 .

  • 1

    我有另一种方法来实现相同的目标,而无需更改基础数据:

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

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

相关问题