代码之家  ›  专栏  ›  技术社区  ›  wishihadabettername

ggplot:如何更改刻面标签?

  •  189
  • wishihadabettername  · 技术社区  · 15 年前

    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 1 , Hosp 2 …)因为它们现在太长并且看起来很狭窄(增加图形的高度不是一个选项,它会占用文档中太多的空间)。我看了看 facet_grid “帮助”页,但无法确定如何使用。

    17 回复  |  直到 6 年前
        1
  •  134
  •   Vince    15 年前

    # 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
  •  309
  •   Axeman    7 年前

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

    假设你的情节是由 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"
    )
    

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


    请注意,这只适用于只有一个面变量。如果有两个方面,那么labeller函数需要为每个方面返回不同的名称向量。您可以通过以下方法来实现:

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

    在哪里? facet1_names facet2_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))
      }
    }
    

    答案改编自 how to change strip.text labels in ggplot with facet and margin=TRUE


    警告 :如果使用此方法通过 性格 this bug report . 在最新版本的ggplot2中修复。

        3
  •  239
  •   mbiron    9 年前

    这里有另一个解决方案,它符合@nout101给出的解决方案的精神,但是更简单,并且没有对最新版本的ggplot2发出警告。

    基本上,首先创建一个命名的字符向量

    hospital_names <- c(
                        `Hospital#1` = "Some Hospital",
                        `Hospital#2` = "Another Hospital",
                        `Hospital#3` = "Hospital Number 3",
                        `Hospital#4` = "The Other Hospital"
                        )
    

    ... + facet_grid(hospital ~ ., labeller = as_labeller(hospital_names))
    

    希望这有帮助。

        4
  •  31
  •   J_F    7 年前

    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

        5
  •  25
  •   domi    9 年前

    如果你有两个方面 hospital room

    facet_grid( hospital ~ room, labeller = labeller(hospital = as_labeller(hospital_names)))
    

    要使用基于向量的方法重命名两个方面(如Noot101的答案所示),可以执行以下操作:

    facet_grid( hospital ~ room, labeller = labeller(hospital = as_labeller(hospital_names),
                                                     room = as_labeller(room_names)))
    
        6
  •  21
  •   jsta    4 年前

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

    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"))
    
        ggplot(dataframe, aes(x = Temperature.C, y = fit)) + 
            geom_line() + 
            facet_wrap(~Humidity.RH., nrow = 2, labeller = hum.names)
    
        7
  •  10
  •   Roman LuÅ¡trik    6 年前

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

        8
  •  9
  •   Matifou    12 年前

     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)
    

    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)
    
        9
  •  8
  •   lillemets    7 年前

    两者 facet_wrap facet_grid 也接受来自的输入 ifelse

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

    如果变量具有更多类别,则 如果不是 nested .

    作为一个副作用,这还允许在 ggplot 打电话。

        10
  •  8
  •   Tung    6 年前

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

    于2019-03-30由 reprex package (v0.2.1.9000)

        11
  •  8
  •   Nick    5 年前

    简单解决方案(来自 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)
    
        12
  •  3
  •   reox    7 年前

    带参数的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)
    
        13
  •  3
  •   Alexander Kielland    7 年前

    因为我还不能对帖子发表评论,所以我把这篇文章作为附录单独发布 Vince's answer son520804's answer . 功劳归他们。

    Son520804:

    使用Iris数据:

    我假设:
    您已经安装了dplyr包,该包具有方便的mutate命令,并且 您的数据集名为survey。 survey %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) 此命令帮助您重命名列,但保留所有其他列。

    使用Vince的iris示例和son520804的部分代码,我使用mutate函数实现了这一点,并且在不接触原始数据集的情况下实现了一个简单的解决方案。 诀窍是创建一个替代名称向量,并在管道中使用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的级别临时更改为包含在新的\u names向量中的相应公共名称。包含

    mutate(Species=new_names) %>%
    

    可以很容易地删除,以显示原来的命名。

    注意事项:

        14
  •  3
  •   Donald Duck user7392049    6 年前

    这对我有用。

    定义一个因素:

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

    使用,在 ggplot() :

    facet_grid( hospitals.factor[hospital] ~ . )
    
        15
  •  2
  •   user4786271    10 年前

    我只是说说他的答案——功劳归他

    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) 
    

        16
  •  2
  •   ytu    8 年前

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

        17
  •  2
  •   jwpfox Amit    7 年前

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

    我假设:

    • 您已安装 dplyr mutate 命令,和
    • 您的数据集命名为 survey .

      突变(Hosp1=Hospital1,Hosp2=Hospital2,…)

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

    那就照做吧 facet_wrap

        18
  •  1
  •   philiporlando    7 年前

    你有没有试过改变你的生活水平 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"
    
        19
  •  1
  •   dani    5 年前

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

    此答案适用于以下情况:

    • 你知道吗
    • 如果你需要的话 表达 bquote )在你的标签和
    • 如果你想要一个独立的 标记名称向量

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

    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

        20
  •  0
  •   Ashirwad    5 年前

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

    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 package (第0.3.0版)