Làm thế nào để thay đổi nhãn khía cạnh?


231

Tôi đã sử dụng ggplotlệnh sau :

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

để sản xuất

văn bản thay thế

Tuy nhiên, tôi muốn thay đổi nhãn khía cạnh thành một cái gì đó ngắn hơn (như Hosp 1, Hosp 2...) vì chúng quá dài và trông chật chội (tăng chiều cao của biểu đồ không phải là một tùy chọn, nó sẽ chiếm quá nhiều không gian trong tài liệu). Tôi đã xem trang trợ giúp facet_grid nhưng không thể tìm ra cách.

Câu trả lời:


124

Thay đổi tên cấp độ yếu tố cơ bản bằng một cái gì đó như:

# 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: Để tránh thay đổi dữ liệu cơ bản, bạn có thể sử dụng: ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
Arnaud A

1
có liên quan ... nếu bạn muốn nhãn bảng điều khiển là biểu thức bquote () (ví dụ levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm))):) nó sẽ không xuất hiện trong biểu thức toán học. Làm thế nào một người sẽ hiển thị biểu thức như nhãn khía cạnh?
Brian D

liên quan đến việc bao gồm các biểu thức trong nhãn khía cạnh, sử dụng labellertùy chọn để facet_grid: stackoverflow.com/questions/37089052/NH
Brian D

285

Đây là một giải pháp tránh chỉnh sửa dữ liệu của bạn:

Giả sử âm mưu của bạn được sắp xếp theo groupmột phần của khung dữ liệu của bạn, có các mức control, test1, test2, sau đó tạo một danh sách được đặt tên theo các giá trị đó:

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

Sau đó tạo chức năng 'labeller' và đẩy nó vào lệnh gọi facet_grid của bạn:

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

Điều này sử dụng các mức của khung dữ liệu để lập chỉ mục danh sách hospital_names, trả về các giá trị danh sách (tên chính xác).


Xin lưu ý rằng điều này chỉ hoạt động nếu bạn chỉ có một biến faceting. Nếu bạn có hai khía cạnh, thì hàm labeller của bạn cần trả về một vectơ tên khác nhau cho mỗi khía cạnh. Bạn có thể làm điều này với một cái gì đó như:

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

Ở đâu facet1_namesfacet2_namesđược danh sách các tên được lập chỉ mục bởi những cái tên chỉ số khía cạnh ( 'Hostpital # 1', vv) được xác định trước.


Chỉnh sửa: Phương pháp trên không thành công nếu bạn vượt qua kết hợp biến / giá trị mà người lao động không biết. Bạn có thể thêm lỗi không an toàn cho các biến không xác định như thế này:

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

Trả lời được điều chỉnh từ cách thay đổi nhãn dải.text trong ggplot với khía cạnh và lề = TRUE


chỉnh sửa: CẢNH BÁO : nếu bạn đang sử dụng phương pháp này để khía cạnh bởi một cột ký tự , bạn có thể nhận được nhãn không chính xác. Xem báo cáo lỗi này . đã sửa trong các phiên bản gần đây của ggplot2.


9
Đẹp, nhưng sẽ không hoạt động với facet_wrap, trong khi giải pháp @Vince cũng sẽ hoạt động với facet_wrap.
Arnaud A

@ArnaudAmzallag: Đúng, mặc dù nếu ai đó cảm thấy muốn quyên góp một thời gian, nó có thể trong tương lai .
ness101

Đã thêm lỗi không an toàn cho các biến số không xác định.
ness101

16
Lưu ý: Điều này không hoạt động trong ggplot2 v.2 - chức năng labeller đã thay đổi. @mbirons trả lời hoạt động stackoverflow.com/a
Andreas

Thú vị, nhưng điều này không phải lúc nào cũng hoạt động, trong khi chỉnh sửa các yếu tố luôn luôn làm.
PatrickT

214

Đây là một giải pháp khác theo tinh thần của @ naught101, nhưng đơn giản hơn và cũng không đưa ra cảnh báo về phiên bản mới nhất của ggplot2.

Về cơ bản, trước tiên bạn tạo một vectơ ký tự được đặt tên

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

Và sau đó, bạn sử dụng nó như một người bán hàng, chỉ bằng cách sửa đổi dòng mã cuối cùng được cung cấp bởi @ naught101 thành

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

Hi vọng điêu nay co ich.


Bản án nào của ggplot2 nằm as_labellertrong? Tôi đã tìm thấy một số mã nguồn cho kho lưu trữ CRAN GitHub , nhưng sau khi nâng cấp lên phiên bản mới nhất (trên CRAN!) Tôi dường như không có chức năng này.
n1k31t4

Lạ nhỉ. Tôi cũng cập nhật thông qua CRAN. Dưới đây là tài liệu docs.ggplot2.org/dev/as_labeller.html
mbiron

4
Điều này thật tuyệt Điều gì xảy ra khi bạn có hai biến trong lưới khía cạnh của bạn? Thích hospital ~ genderhay sao? Có cách nào để sử dụng lao động trên cả hai trục không? Tôi không thể thấy bất cứ điều gì rõ ràng trong các tài liệu.
nè 101

3
Lưu ý nếu bạn bắt đầu với câu trả lời của naught, thì câu trả lời này chỉ hoạt động với c () chứ không phải danh sách () .
thomas88wp

1
Một phần tuyệt vời của điều này là nó hoạt động với cả hai trục của lưới mặt!
Calum You

30

Đây là cách tôi đã làm với facet_grid(yfacet~xfacet)việc sử dụng ggplot2, phiên bản 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")
    )
)

Lưu ý rằng điều này không chứa một cuộc gọi đến as_labeller()- một cái gì đó mà tôi đã vật lộn trong một thời gian.

Cách tiếp cận này được lấy cảm hứng từ ví dụ cuối cùng trên trang trợ giúp Coced to labeller .


những công việc này!!! Tôi không thể áp dụng các giải pháp khác vì một số giải pháp được đề xuất không dùng nữa trên các phiên bản ggplot2 hiện tại.
yanes

Bạn có thể xây dựng các vectơ được đặt tên này với setNames() stackoverflow.com/a/22428439/3362993
jsta

23

Nếu bạn có hai khía cạnh hospitalroommuốn đổi tên chỉ một, bạn có thể sử dụng:

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

Để đổi tên hai khía cạnh bằng cách sử dụng phương pháp dựa trên vectơ (như trong câu trả lời của naught101), bạn có thể làm:

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

16

Cách dễ nhất để thay đổi mà KHÔNG sửa đổi dữ liệu cơ bản là:

1) Tạo một đối tượng bằng cách sử dụng as_labellerchức năng thêm dấu tick phía sau cho mỗi giá trị mặc định :

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) Chúng tôi thêm vào GGplot:

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

1
Tôi nghĩ đây là phương pháp tao nhã nhất - nó hiệu quả và hoạt động với ggplot2 phiên bản 3.0.0.9000
Landak

9

Lưu ý rằng giải pháp này sẽ không hoạt động tốt trong trường hợp ggplot sẽ hiển thị ít yếu tố hơn so với biến của bạn thực sự chứa (điều này có thể xảy ra nếu bạn đã ví dụ như đặt lại):

 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)

Một giải pháp đơn giản (bên cạnh việc thêm tất cả các yếu tố không được sử dụng trong name_li, có thể tẻ nhạt) là loại bỏ các yếu tố không được sử dụng với droplevels (), trong tập dữ liệu gốc hoặc trong hàm labbeler, xem:

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

Giải pháp này rất gần với những gì @domi có, nhưng được thiết kế để rút ngắn tên bằng cách tìm nạp 4 chữ cái đầu tiên và số cuối cùng.

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

nhập mô tả hình ảnh ở đây


6

Cả hai facet_wrapfacet_gridcũng chấp nhận đầu vào từ ifelsenhư là một đối số. Vì vậy, nếu biến được sử dụng cho faceting là logic, thì giải pháp rất đơn giản:

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

Nếu biến có nhiều loại hơn, ifelsecâu lệnh cần được lồng .

Là một tác dụng phụ, điều này cũng cho phép tạo ra các nhóm được khía cạnh trong ggplotcuộc gọi.


5

Thêm một giải pháp khác tương tự như @ domi với phân tích cú pháp các ký hiệu toán học, siêu ký tự, ký tự phụ, dấu ngoặc đơn / ngoặc vuông, .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}, "]"))))

Được tạo vào ngày 2019-03-30 bởi gói reprex (v0.2.1.9000)



3

Tôi nghĩ rằng tất cả các giải pháp khác thực sự hữu ích để làm điều này, nhưng vẫn còn một cách khác.

Tôi giả sử:

  • bạn đã cài đặt dplyrgói, có mutatelệnh thuận tiện và
  • tập dữ liệu của bạn được đặt tên survey.

    khảo sát%>% đột biến (Aid1 = Hospital1, Aid2 = Hospital2, ........)

Lệnh này giúp bạn đổi tên các cột, nhưng tất cả các cột khác được giữ lại.

Sau đó làm tương tự facet_wrap, bây giờ bạn ổn.


xin lỗi, nó không hoạt động vì nó cũng thay đổi nội dung cột
Jens

3

Chức năng của labeller với các variable, valueđối số sẽ không hoạt động đối với tôi. Ngoài ra nếu bạn muốn sử dụng biểu thức, bạn cần sử dụng lapply và không thể sử dụng đơn giản arr[val], vì đối số của hàm là data.frame.

Mã này đã làm việc:

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

Vì tôi chưa được phép bình luận về các bài đăng, nên tôi đăng riêng bài này dưới dạng phụ lục cho câu trả lời của Vincecâu trả lời của son520804 . Tín dụng cho họ.

Son520804:

sử dụng dữ liệu Iris:

Tôi giả sử:
Bạn đã cài đặt gói dplyr, có lệnh biến đổi thuận tiện và tập dữ liệu của bạn được đặt tên là khảo sát. survey %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) Lệnh này giúp bạn đổi tên các cột, nhưng tất cả các cột khác được giữ lại. Sau đó, làm facet_wrap tương tự, bây giờ bạn ổn.

Sử dụng ví dụ iris của Vince và mã một phần của son520804, tôi đã làm điều này với chức năng đột biến và đạt được một giải pháp dễ dàng mà không cần chạm vào tập dữ liệu gốc. Mẹo nhỏ là tạo một vectơ tên đứng và sử dụng mutate () bên trong đường ống để sửa tên tạm thời:

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

Trong ví dụ này, bạn có thể thấy các mức của i $ Species tạm thời được thay đổi thành các tên phổ biến tương ứng có trong vectơ new_names. Dòng chứa

mutate(Species=new_names) %>%

có thể dễ dàng được gỡ bỏ để tiết lộ tên ban đầu.

Lưu ý: Điều này có thể dễ dàng đưa ra các lỗi trong tên nếu vectơ new_name không được thiết lập chính xác. Có lẽ sẽ sạch sẽ hơn nhiều khi sử dụng một hàm riêng để thay thế các chuỗi biến. Hãy nhớ rằng vectơ new_name có thể cần phải được lặp lại theo nhiều cách khác nhau để khớp với thứ tự của tập dữ liệu gốc của bạn. Vui lòng kiểm tra hai lần và ba lần xem điều này có đạt được chính xác không.


Nó có thể đẹp hơn một chút để sử dụng: new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris')và sau đó, trong trường hợp đột biến, bạn có thể tạo một cột mới:mutate(Spec = new_names[Species])
filups21

3

Đây là làm việc cho tôi.

Xác định một yếu tố:

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

và sử dụng, trong ggplot():

facet_grid( hospitals.factor[hospital] ~ . )

2

Chỉ cần mở rộng câu trả lời của naught101 - tín dụng sẽ đến với anh ta

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

Những gì bạn phải làm là tạo một danh sách với ánh xạ tên-tên

clusteringDistance_names <- list(
  '100'="100",
  '200'="200",
  '300'="300",
  '400'="400",
  '600'="500"
)

và xác định lại plot_labeller()với các đối số mặc định mới:

plot_labeller <- function(variable,value, facetVar1='clusteringDistance', var1NamesMapping=clusteringDistance_names, facetVar2='', var1NamesMapping=list() )

Và sau đó:

ggplot() + 
  facet_grid(clusteringDistance ~ . , labeller=plot_labeller) 

Ngoài ra, bạn có thể tạo một chức năng chuyên dụng cho từng thay đổi nhãn bạn muốn có.


2

Tôi có một cách khác để đạt được cùng một mục tiêu mà không thay đổi dữ liệu cơ bản:

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

Những gì tôi đã làm ở trên là thay đổi nhãn của yếu tố trong khung dữ liệu gốc và đó là điểm khác biệt duy nhất so với mã gốc của bạn.


1

Bạn đã thử thay đổi cấp độ cụ thể của Hospitalvector của bạn ?

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

Tôi cảm thấy mình nên thêm câu trả lời của mình vào đây vì tôi mất khá nhiều thời gian để thực hiện công việc này:

Câu trả lời này là dành cho bạn nếu:

  • bạn không muốn chỉnh sửa dữ liệu gốc của mình
  • nếu bạn cần biểu thức ( bquote) trong nhãn của bạn và
  • nếu bạn muốn sự linh hoạt của một vectơ tên nhãn riêng

Về cơ bản, tôi đặt các nhãn trong một vectơ có tên để các nhãn không bị lẫn lộn hoặc chuyển đổi. Các labellerbiểu hiện có thể có thể được đơn giản hơn, nhưng điều này tại các công trình ít nhất (cải tiến đang rất chào đón). Lưu ý `(dấu ngoặc kép) để bảo vệ yếu tố khía cạnh.

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

nhập mô tả hình ảnh ở đây


1

Giải pháp đơn giản (từ đây ):

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

Sau khi vật lộn một thời gian, những gì tôi thấy là chúng ta có thể sử dụng fct_relevel()fct_recode()từ forcatskết hợp để thay đổi thứ tự của các khía cạnh cũng như sửa chữa các nhãn khía cạnh. Tôi không chắc nếu nó được hỗ trợ bởi thiết kế, nhưng nó hoạt động! Kiểm tra các lô dưới đây:

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

Được tạo vào ngày 2020/02/2016 bởi gói reprex (v0.3.0)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.