Як змінити фацетні мітки?


230

Я використав таку 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 текст

Я хотів би змінити фасети ярликів, однак, до чого - то більш короткому (як Hosp 1, Hosp 2...) , тому що вони занадто довго і виглядають звели (збільшення висоти графіки не варіант, це зайняло б занадто багато місця в документ). Я переглянув довідкову сторінку facet_grid, але не можу зрозуміти, як.

Відповіді:


123

Змініть основні імена рівня фактора чимось на кшталт:

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

12
@wishihadabettername: Щоб уникнути зміни базових даних, ви можете використовувати: ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
Arnaud A

1
пов'язане ... якщо ви хочете, щоб мітка панелі була виразом bquote () (наприклад, levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm)))), вона не з’явиться в математичному виразі. Як можна відображати вирази як фацетні мітки?
Брайан Д

, пов’язані з включенням виразів у фацетну мітку, використовуйте labellerваріант для facet_grid: stackoverflow.com/questions/37089052/…
Brian D

285

Ось рішення, яке дозволяє уникнути редагування даних:

Скажіть, що ваш сюжет огранений 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)
 ...

При цьому використовуються рівні кадру даних для індексації списку імен лікарень, повертаючи значення списку (правильні назви).


Зверніть увагу, що це працює лише в тому випадку, якщо у вас є лише одна змінна грані. Якщо у вас є дві грані, ваша функція маркера повинна повертати інший вектор імені для кожної грані. Ви можете зробити це за допомогою:

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

Де facet1_namesі facet2_namesє заздалегідь визначені списки імен, індексованих фасетними іменами індексу ("Хостпіталь №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 з фасетою та запасом = ІСТИНА


редагувати: ПОПЕРЕДЖЕННЯ : якщо ви використовуєте цей метод для фасетування стовпців символів , ви можете отримати неправильні мітки. Побачити цей звіт про помилку . виправлено в останніх версіях ggplot2.


9
Приємно, але не буде працювати з facet_wrap, тоді як рішення @Vince також буде працювати з facet_wrap.
Арно А

@ArnaudAmzallag: Правильно, хоча якщо хтось відчуває, як пожертвувати якийсь час, це може бути в майбутньому .
naught101

Додано захист від помилок для невідомих фацетних змінних.
naught101

16
Примітка. Це не працює в ggplot2 v.2 - функція етикеток змінилася. @mbirons відповідь працює stackoverflow.com/a/34811062/162832
Andreas

Цікаво, але це не завжди працює, тоді як редагування факторів завжди є.
PatrickT

214

Ось ще одне рішення, яке відповідає дусі рішення, подане @ 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))

Сподіваюсь, це допомагає.


У якій версії ggplot2 знаходиться as_labeller? Я знайшов вихідний код у сховищі CRAN GitHub , але після оновлення до останньої версії (на CRAN!) Я, здається, не функціонував.
n1k31t4

Це дивно. Я також оновлювався через CRAN. Ось документація docs.ggplot2.org/dev/as_labeller.html
mbiron

4
Це круто. Що відбувається, якщо у вашій грані сітки є дві змінні? Як, hospital ~ genderчи щось? Чи є спосіб використання етикеток на обох осях? Я не бачу нічого очевидного в документах.
naught101

3
Зверніть увагу, якщо ви почали з відповіді нуля, цей працює лише з c (), а не з списком () .
thomas88wp

1
Важлива частина цього полягає в тому, що це працює з обома осями фацетної сітки!
Calum You

30

Ось як я це зробив за 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()чогось, з чим я боровся деякий час.

Цей підхід натхненний останнім прикладом на сторінці довідки примусити функцію етикеток .


це працює !!! Я не зміг застосувати інші рішення, оскільки деякі запропоновані рішення були застаріли в поточних версіях ggplot2.
yanes

Ви можете побудувати ці названі вектори з setNames() stackoverflow.com/a/22428439/3362993
jsta

23

Якщо у вас є два аспекти 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)))

16

Найпростіший спосіб зміни БЕЗ модифікації базових даних:

1) Створіть об'єкт за допомогою as_labellerфункції додавання зворотного галочки для кожного зі значень за замовчуванням :

hum.names <- as_labeller(c(`50` = "RH% 50", `60` = "RH% 60",`70` = "RH% 70", `80` = "RH% 80",`90` = "RH% 90", `100` = "RH% 100")) #Necesarry to put RH% into the facet labels

2) Додаємо в GGplot:

ggplot(dataframe, aes(x=Temperature.C,y=fit))+geom_line()+ facet_wrap(~Humidity.RH., nrow=2,labeller=hum.names)

1
Це, на мій погляд, найелегантніший метод - він ефективний і працює з ggplot2 версії 3.0.0.9000
Landak

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, що може бути стомлюючим) - це скинути невикористані фактори за допомогою крапельниць () або в оригінальний набір даних, або у функцію лабораторії, див.

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

Це рішення дуже близьке до того, що має @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))

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


6

І те, facet_wrapі facet_gridтакож приймають дані ifelseяк аргумент. Отже, якщо змінна, яка використовується для облицювання, є логічною, рішення дуже просте:

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

Якщо змінна має більше категорій, ifelseоператор потрібно вкласти .

Як побічний ефект, це також дозволяє створити групи, які повинні бути вирішені в рамках ggplotвиклику.


5

Додавання іншого рішення, схожого на @ domi's, з розбором математичних символів, суперскриптом, індексом, дужкою / дужкою, .etc.

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 (v0.2.1.9000)



3

Я думаю, що всі інші рішення дуже корисні для цього, але є ще один спосіб.

Я вважаю:

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

    опитування%>% мутації (Hosp1 = Hospital1, Hosp2 = Hospital2, ........)

Ця команда допомагає перейменовувати стовпці, але всі інші стовпці зберігаються.

Тоді зробіть те ж саме facet_wrap, вам зараз добре.


Вибачте, це не працює, оскільки він також змінює вміст стовпця
Єнс,

3

Визначення функції labeller з variable, valueаргументами для мене не працює. Крім того, якщо ви хочете використовувати вираз, вам потрібно скористатися лаптопно, а не можете їх просто використовувати 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)

3

Так як я ще не дозволено коментувати повідомлення, я відправляю це окремо в якості доповнення до відповіді Вінса і відповідь son520804 в . Кредит йде їм.

Son520804:

за допомогою даних Іриса:

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

Використовуючи приклад райдужки Вінса та частковий код son520804, я зробив це за допомогою функції мутації та досягнув простого рішення, не торкаючись початкового набору даних. Трюк полягає в тому, щоб створити вектор імені очікування та використовувати 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 може знадобитися повторити різними способами, щоб відповідати порядку вашого початкового набору даних. Будь ласка, двічі і втричі перевірте, чи правильно це досягнуто.


Використовувати це може бути трохи приємніше: new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris')і тоді в мутації ви можете створити новий стовпець таким чином:mutate(Spec = new_names[Species])
filups21

3

Це працює для мене.

Визначте фактор:

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

і використовувати в ggplot():

facet_grid( hospitals.factor[hospital] ~ . )

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) 

Крім того, ви можете створити виділену функцію для кожної зміни мітки, яку ви хочете мати.


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

Те, що я зробив вище, - це зміна міток фактору в початковому кадрі даних, і це єдина відмінність порівняно з вашим вихідним кодом.


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"

1

Я відчуваю, що мені слід додати свою відповідь до цього, тому що мені знадобилося досить багато часу, щоб зробити цю роботу:

Ця відповідь для вас, якщо:

  • ви не хочете редагувати свої вихідні дані
  • якщо вам потрібні вирази ( 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')

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


1

Просте рішення ( звідси ):

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)

0

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

Створено 2020-02-16 пакетом reprex (v0.3.0)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.