Как изменить метки фасетов?

Я использовал следующую команду 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 1, _4 _...), потому что они сейчас слишком длинные и выглядят тесными (увеличение высоты графика не является проблемой вариант, это займет слишком много места в документе). Я просмотрел справочную страницу facet_grid, но не могу понять, как это сделать.


person wishihadabettername    schedule 13.08.2010    source источник
comment
Большинство ответов очень подробны. Я нашел простой ответ (community.rstudio.com/t/ change-sep-in-labeller / 7369/2) и сделал с ним пример. См. Ниже.   -  person Samuel Saari    schedule 09.07.2021


Ответы (21)


Измените имена базовых уровней факторов на что-то вроде:

# 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 ~ .)
person Vince    schedule 13.08.2010
comment
@wishihadabettername: Чтобы избежать изменения базовых данных, вы можете использовать: ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .) - person Arnaud A; 12.05.2014
comment
связанные ... если вы хотите, чтобы метка панели была выражением bquote () (например, levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm)))), она не будет отображаться в математическом выражении. Как отобразить выражения в виде меток фасетов? - person Brian D; 21.02.2018
comment
связанных с включением выражений в метку фасета, используйте параметр labeller для facet_grid: stackoverflow.com/questions/37089052/ - person Brian D; 21.02.2018

Вот решение, позволяющее избежать редактирования ваших данных:

Скажем, ваш график фасетирован 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, возвращая значения списка (правильные имена).


Обратите внимание, что это работает, только если у вас есть только одна переменная фасетирования. Если у вас есть два фасета, ваша функция этикетировщика должна возвращать другой вектор имени для каждого фасета. Вы можете сделать это примерно так:

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

Ответ адаптирован из как изменить метки strip.text в ggplot с фасетом и полем = ИСТИНА


edit: ПРЕДУПРЕЖДЕНИЕ: если вы используете этот метод для фасетирования столбца символом, вы можете получать неправильные метки. См. этот отчет об ошибке. исправлено в последних версиях ggplot2.

person naught101    schedule 24.08.2012
comment
Хорошо, но не будет работать с facet_wrap, тогда как решение @Vince будет работать и с facet_wrap. - person Arnaud A; 12.05.2014
comment
@ArnaudAmzallag: Верно, хотя, если кто-то захочет пожертвовать время, это может быть в будущем. - person naught101; 13.05.2014
comment
Добавлен отказоустойчивый для неизвестных переменных фасетирования. - person naught101; 11.12.2014
comment
Примечание: это не работает в ggplot2 v.2 - функция этикетировщика изменилась. @mbirons answer работает stackoverflow.com/a/34811062/162832 - person Andreas; 18.01.2016
comment
Интересно, но это не всегда работает, тогда как редактирование факторов всегда работает. - person PatrickT; 01.11.2017
comment
Следует ли повторять переменную более высокого порядка в facet1_names? - person wolfsatthedoor; 11.07.2020

Вот еще одно решение, которое в духе того, что дано @ 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))

Надеюсь это поможет.

person mbiron    schedule 15.01.2016
comment
В какой версии ggplot2 as_labeller? Я нашел исходный код в репозитории CRAN GitHub, но после обновления до последней версии (на CRAN!) у меня, похоже, не работает эта функция. - person n1k31t4; 25.01.2016
comment
Это странно. Я тоже через CRAN обновлялся. Вот документация docs.ggplot2.org/dev/as_labeller.html - person mbiron; 25.01.2016
comment
Это круто. Но что происходит, когда у вас есть две переменные в вашей фасетной сетке? Типа hospital ~ gender или что-то в этом роде? Есть ли способ использовать этикетировочные машины на обеих осях? Я не вижу ничего очевидного в документации. - person naught101; 21.07.2016
comment
Обратите внимание, если вы начали с нулевого ответа, этот работает только с c (), а не с list (). - person thomas88wp; 19.01.2018
comment
Одна замечательная часть этого заключается в том, что это работает с обеими осями фасетной сетки! - person Calum You; 09.10.2018
comment
ответ на вопрос @ naught101 будет ответом от domi: stackoverflow.com/a/37778906/8124725 Без этого кроме того, это не работает для меня, давая NA для переменной, которую я не включил. - person 4rj4n; 03.02.2020
comment
Как это сделать, если у вас есть две грани? - person wolfsatthedoor; 11.07.2020
comment
@wolfsatthedoor посмотрите ответ @bovender - person mbiron; 11.07.2020
comment
@mbiron да, но это два аспекта X, а не X и Y - person wolfsatthedoor; 11.07.2020

Вот как я сделал это с 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() - то, с чем я боролся некоторое время.

Этот подход основан на последнем примере на странице справки Принуждение к функции маркировщика.

person bovender    schedule 20.03.2017
comment
это работает!!! Я не смог применить другие решения, потому что некоторые из предложенных решений устарели в текущих версиях ggplot2. - person yanes; 01.04.2017
comment
Вы можете построить эти именованные векторы с помощью setNames() stackoverflow.com/a/22428439/3362993 - person jsta; 06.09.2018

Если у вас есть два фасета 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)))
person domi    schedule 12.06.2016
comment
Это дает мне НА для всех ярлыков :( - person wolfsatthedoor; 11.07.2020

САМЫЙ ПРОСТОЙ способ изменить БЕЗ изменения базовых данных:

  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)
person Leinfloyd    schedule 26.02.2019
comment
Я считаю, что это самый элегантный метод - он эффективен и работает с ggplot2 версии 3.0.0.9000. - person Landak; 27.06.2019
comment
но это не работает, когда есть два аспекта, например, введите ~ Humidity - person Denis Cousineau; 17.03.2021

Это решение очень похоже на то, что есть в @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))

введите описание изображения здесь

person Roman Luštrik    schedule 23.09.2018

Добавление другого решения, аналогичного @ 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}, "]"))))

Создано 30 марта 2019 г. пакетом REPEX (v0.2.1.9000)

person Tung    schedule 31.03.2019
comment
См. также - person Tung; 31.03.2019

Простое решение (здесь):

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)
person Nick    schedule 29.04.2020

Обратите внимание, что это решение не будет работать хорошо, если 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)
person Matifou    schedule 11.06.2013

И facet_wrap, и facet_grid также принимают ввод от ifelse в качестве аргумента. Итак, если переменная, используемая для фасетирования, логична, решение очень простое:

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

Если у переменной больше категорий, оператор ifelse должен быть вложенным.

В качестве побочного эффекта это также позволяет фасетировать создание групп в вызове ggplot.

person lillemets    schedule 08.11.2017

Определение функции 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)
person reox    schedule 04.08.2018

Поскольку мне еще не разрешено комментировать сообщения, я публикую это отдельно как дополнение к ответу Винса и ответ son520804. Им идет заслуга.

Сын520804:

с использованием данных Iris:

Я предполагаю:
Вы установили пакет dplyr, в котором есть удобная команда mutate, и ваш набор данных называется survey. survey %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) Эта команда помогает вам переименовывать столбцы, но все остальные столбцы сохраняются. Затем сделайте то же самое facet_wrap, теперь все в порядке.

Используя пример радужной оболочки Винса и частичный код 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 может потребоваться повторять по-разному, чтобы соответствовать порядку в исходном наборе данных. Пожалуйста, дважды - и - трижды проверьте, правильно ли это выполнено.

person Alexander Kielland    schedule 21.08.2018
comment
Возможно, будет немного лучше использовать: new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris'), а затем в мутации вы можете создать новый столбец следующим образом: mutate(Spec = new_names[Species]) - person filups21; 05.02.2019

Это работает для меня.

Определите фактор:

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

и используйте в ggplot():

facet_grid( hospitals.factor[hospital] ~ . )
person Hernán Castelo    schedule 16.12.2018

Просто расширяю ответ 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) 

В качестве альтернативы вы можете создать специальную функцию для каждого изменения метки, которое вы хотите иметь.

person user4786271    schedule 17.06.2015

У меня есть другой способ достичь той же цели без изменения базовых данных:

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

То, что я сделал выше, - это изменение меток фактора в исходном фрейме данных, и это единственное отличие по сравнению с исходным кодом.

person ytu    schedule 10.03.2017

Я думаю, что все другие решения действительно полезны для этого, но есть еще один способ.

Я предполагаю:

  • вы установили пакет dplyr, в котором есть удобная команда mutate, и
  • ваш набор данных называется survey.

    опрос%>% mutate (Hosp1 = Hospital1, Hosp2 = Hospital2, ........)

Эта команда помогает вам переименовывать столбцы, но все остальные столбцы сохраняются.

Тогда сделайте то же самое facet_wrap, теперь у вас все в порядке.

person son520804    schedule 19.12.2017
comment
извините, это не работает, так как также меняет содержимое столбца - person Jens; 19.07.2018
comment
Это неверно, так как: 1. разные переменные Hosp1, Hosp2 ... не существуют. В исходном вопросе используется один столбец с именем больница, в котором содержатся строки 2. даже если у вас есть разные столбцы, ваша команда будет искать объекты с именем больница1, больница2 и т. Д. И выдаст ошибку, потому что они не существуют. 3. как сказал @Jens, если вы вместо этого используете строки, то есть Hospital1, он заполнит весь столбец этим значением. Возможно, вы ищете mutate() в сочетании с case_when()? Не уверен, почему за это проголосовали, так как это определенно не сработает. - person stragu; 19.09.2020

Вы пробовали изменить конкретные уровни вашего 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"
person philiporlando    schedule 28.04.2018

Я чувствую, что должен добавить свой ответ на этот вопрос, потому что мне потребовалось довольно много времени, чтобы это сработало:

Этот ответ для вас, если:

  • вы не хотите редактировать исходные данные
  • если вам нужны выражения (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')

введите здесь описание изображения

person dani    schedule 09.10.2019

После некоторой борьбы я обнаружил, что мы можем использовать 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

Создано 16 февраля 2020 г. пакетом REPEX (v0.3.0)

person Ashirwad    schedule 16.02.2020

Один лайнер от 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 = " #"))

Создано 2021-07-09 пакетом REPEX (v2.0.0)

person Samuel Saari    schedule 09.07.2021