Как изменить метки фасетов?
Я использовал следующую команду 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, но не могу понять, как это сделать.
Ответы
Ответ 1
Измените имена базового уровня факторов следующим образом:
# 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
Вот решение, которое позволяет избежать редактирования ваших данных:
Скажем, ваш график огранен group
частью вашего фрейма данных, который имеет control, test1, test2
уровней 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 с помощью facet и margin = TRUE
edit: ПРЕДУПРЕЖДЕНИЕ: если вы используете этот метод для фасетирования столбца символов, возможно, вы получаете неправильные метки. Смотрите этот отчет об ошибке. исправлено в последних версиях ggplot2.
Ответ 3
Здесь другое решение, которое в духе того, которое дано @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))
Надеюсь, что это поможет.
Ответ 4
Вот как я это сделал с 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()
- то, с чем я боролся некоторое время.
Этот подход вдохновлен последним примером на странице справки "Привести к функции labeller".
Ответ 5
Если у вас есть две грани 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)))
Ответ 6
Обратите внимание, что это решение не будет работать хорошо, если 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, см.:
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)
Ответ 7
Это решение очень близко к тому, что имеет @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
Самый простой способ изменить БЕЗ изменения основных данных:
1) Создайте объект с as_labeller
функции 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)
Ответ 9
Оба facet_wrap
и facet_grid
также принимают ввод из ifelse
в качестве аргумента. Поэтому, если переменная, используемая для огранки, логична, решение очень просто:
facet_wrap(~ifelse(variable, "Label if true", "Label if false"))
Если переменная имеет больше категорий, оператор ifelse
должен быть вложенным.
В качестве побочного эффекта это также позволяет создавать группы в гранях ggplot
.
Ответ 10
Добавление другого решения, похожего на @domi, с разбором математических символов, надстрочного индекса, нижнего индекса, скобок/скобок,.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 пакетом представлением (v0.2.1.9000)
Ответ 11
Я думаю, что все другие решения действительно полезны для этого, но есть еще один способ.
Я предполагаю:
- вы установили пакет
dplyr
, который имеет удобную команду mutate
, и -
Ваш набор данных называется survey
.
Опрос%>% мутации (Hosp1 = Больница1, Hosp2 = Больница2,........)
Эта команда помогает вам переименовывать столбцы, но все остальные столбцы сохраняются.
Затем сделайте то же самое facet_wrap
, теперь вы в порядке.
Ответ 12
Определение функции 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
Поскольку мне пока не разрешено комментировать сообщения, я публикую это отдельно как дополнение к ответу Винса и ответу son520804. Кредит идет им.
Son520804:
используя данные 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 ~ .)
В этом примере вы можете видеть, что уровни я $ Species временно изменяются на соответствующие общие имена, содержащиеся в векторе new_names. Строка, содержащая
mutate(Species=new_names) %>%
может быть легко удален, чтобы показать оригинальное наименование.
Предупреждение: это может легко привести к ошибкам в именах, если вектор new_name настроен неправильно. Вероятно, было бы намного понятнее использовать отдельную функцию для замены переменных строк. Имейте в виду, что вектор new_name может потребоваться повторять различными способами, чтобы соответствовать порядку вашего исходного набора данных. Пожалуйста, дважды и трижды проверьте, что это правильно достигнуто.
Ответ 14
Просто продолжая 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)
В качестве альтернативы вы можете создать специальную функцию для каждой из изменений метки, которые вы хотите иметь.
Ответ 15
У меня есть другой способ достичь той же цели, не изменяя основные данные:
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())
Что я делал выше, это изменение меток фактора в исходном кадре данных, и это единственное отличие по сравнению с вашим исходным кодом.
Ответ 16
Вы пытались изменить конкретные уровни вашего 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"
Ответ 17
Это работает для меня.
Определите фактор:
hospitals.factor<- factor( c("H0","H1","H2") )
и используйте в ggplot()
:
facet_grid( hospitals.factor[hospital] ~ . )
Ответ 18
Я чувствую, что должен добавить свой ответ к этому, потому что мне потребовалось довольно много времени, чтобы сделать эту работу:
Этот ответ для вас, если:
- Вы не хотите редактировать исходные данные
- если вам нужны выражения (
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')
![enter image description here]()