Bagaimana cara mengubah label facet?

231

Saya telah menggunakan ggplotperintah berikut :

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

untuk menghasilkan

teks alternatif

Saya ingin mengubah label sisi , menjadi sesuatu yang lebih pendek (seperti Hosp 1, Hosp 2...) karena labelnya terlalu panjang sekarang dan terlihat sempit (menambah ketinggian grafik bukanlah suatu pilihan, itu akan memakan terlalu banyak tempat di dokumen). Saya melihat halaman bantuan facet_grid tetapi tidak tahu caranya.

wishihadabettername
sumber

Jawaban:

124

Ubah nama level faktor yang mendasarinya dengan sesuatu seperti:

# 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 ~ .)
Vince
sumber
12
@wishihadabettername: Untuk menghindari perubahan data yang mendasarinya, Anda dapat menggunakan: ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
Arnaud A
1
terkait ... jika Anda ingin label panel menjadi ekspresi bquote () (mis., levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm)))) label itu tidak akan muncul dalam ekspresi matematika. Bagaimana seseorang menunjukkan ekspresi sebagai label facet?
Brian D
terkait untuk memasukkan ekspresi dalam label facet, gunakan labelleropsi untuk facet_grid: stackoverflow.com/questions/37089052/…
Brian D
285

Berikut ini adalah solusi yang menghindari pengeditan data Anda:

Katakanlah plot groupAnda difasilitasi oleh bagian kerangka data Anda, yang memiliki level control, test1, test2, lalu buat daftar yang dinamai dengan nilai-nilai tersebut:

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

Kemudian buat fungsi 'labeller', dan dorong ke dalam panggilan facet_grid Anda:

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

Ini menggunakan tingkat bingkai data untuk mengindeks daftar nama_rumah sakit, mengembalikan nilai daftar (nama yang benar).


Harap dicatat bahwa ini hanya berfungsi jika Anda hanya memiliki satu variabel faceting. Jika Anda memiliki dua sisi, maka fungsi labeller Anda harus mengembalikan vektor nama yang berbeda untuk setiap sisi. Anda dapat melakukan ini dengan sesuatu seperti:

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

Di mana facet1_namesdan facet2_namesmerupakan daftar nama yang ditentukan sebelumnya yang diindeks oleh nama indeks facet ('Hostpital # 1', dll.).


Sunting: Metode di atas gagal jika Anda meneruskan kombinasi variabel / nilai yang tidak diketahui labeller. Anda dapat menambahkan gagal-aman untuk variabel tidak dikenal seperti ini:

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

Jawaban diadaptasi dari cara mengganti label strip.text di ggplot dengan facet dan margin = TRUE


edit: PERINGATAN : jika Anda menggunakan metode ini untuk facet oleh kolom karakter , Anda mungkin mendapatkan label yang salah. Lihat laporan bug ini . diperbaiki dalam versi terbaru ggplot2.

tidak ada apa-apa101
sumber
9
Bagus, tetapi tidak akan bekerja dengan facet_wrap, sedangkan solusi @Vince akan bekerja dengan facet_wrap juga.
Arnaud A
@ArnaudAmzallag: Benar, meskipun jika seseorang merasa ingin menyumbangkan waktu, itu bisa terjadi di masa depan .
naught101
Menambahkan kegagalan-aman untuk variabel facetting yang tidak dikenal.
naught101
16
Perhatian: Ini tidak berfungsi di ggplot2 v.2 - fungsi labeller telah berubah. @mbirons answer works stackoverflow.com/a/34811062/162832
Andreas
Menarik, tetapi ini tidak selalu berhasil, sedangkan mengedit faktor selalu berhasil.
Patrick
214

Inilah solusi lain yang sesuai dengan semangat yang diberikan oleh @naught101, tetapi lebih sederhana dan juga tidak memberikan peringatan pada versi terbaru ggplot2.

Pada dasarnya, Anda pertama kali membuat vektor karakter bernama

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

Dan kemudian Anda menggunakannya sebagai labeller, hanya dengan memodifikasi baris terakhir dari kode yang diberikan oleh @ naught101 ke

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

Semoga ini membantu.

mbiron
sumber
Di mana verison ggplot2 berada as_labeller? Saya telah menemukan beberapa kode sumber untuk di repositori CRAN GitHub , tetapi setelah memutakhirkan ke versi terbaru (pada CRAN!) Saya sepertinya tidak memiliki fungsi.
n1k31t4
Itu aneh. Saya juga memperbarui melalui CRAN. Inilah dokumentasi docs.ggplot2.org/dev/as_labeller.html
mbiron
4
Ini keren. Apa yang terjadi ketika Anda memiliki dua variabel di facet grid Anda? Suka hospital ~ genderatau apalah? Apakah ada cara untuk menggunakan labeller pada kedua sumbu? Saya tidak bisa melihat sesuatu yang jelas di dokumen.
naught101
3
Perhatikan jika Anda mulai dengan jawaban nol, jawaban ini hanya berfungsi dengan c () bukan daftar () .
thomas88wp
1
Salah satu bagian besar dari ini adalah bahwa ini bekerja dengan kedua sumbu dari grid segi!
Calum You
30

Inilah cara saya melakukannya dengan facet_grid(yfacet~xfacet)menggunakan ggplot2, versi 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")
    )
)

Perhatikan bahwa ini tidak mengandung panggilan ke as_labeller()- sesuatu yang saya perjuangkan untuk sementara waktu.

Pendekatan ini diilhami oleh contoh terakhir pada halaman bantuan fungsi Coeller to labeller .

bovender
sumber
ini bekerja!!! Saya tidak dapat menerapkan solusi lain karena beberapa solusi yang disarankan sudah usang pada versi ggplot2 saat ini.
yanes
Anda dapat membuat vektor-vektor bernama ini dengan setNames() stackoverflow.com/a/22428439/3362993
jsta
23

Jika Anda memiliki dua sisi hospitaldan roomingin mengubah nama hanya satu, Anda dapat menggunakan:

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

Untuk mengganti nama dua sisi menggunakan pendekatan berbasis vektor (seperti pada jawaban naught101), Anda dapat melakukan:

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

Cara termudah untuk berubah TANPA mengubah data yang mendasarinya adalah:

1) Buat objek menggunakan as_labellerfungsi menambahkan tanda centang kembali untuk masing-masing nilai default :

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) Kami menambahkan ke dalam GGplot:

ggplot(dataframe, aes(x=Temperature.C,y=fit))+geom_line()+ facet_wrap(~Humidity.RH., nrow=2,labeller=hum.names)
Leinfloyd
sumber
1
Ini menurut saya adalah metode yang paling elegan - efektif dan bekerja dengan ggplot2 versi 3.0.0.9000
Landak
9

Perhatikan bahwa solusi ini tidak akan berfungsi dengan baik seandainya ggplot akan menunjukkan lebih sedikit faktor daripada variabel Anda yang sebenarnya berisi (yang bisa terjadi jika Anda misalnya berlangganan):

 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)

Solusi sederhana (selain menambahkan semua faktor yang tidak digunakan dalam names_li, yang bisa membosankan) adalah dengan menjatuhkan faktor yang tidak digunakan dengan droplevels (), baik dalam dataset asli, atau dalam fungsi labbeler, lihat:

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)
Matifou
sumber
9

Solusi ini sangat dekat dengan apa yang dimiliki @domi, tetapi dirancang untuk mempersingkat nama dengan mengambil 4 huruf pertama dan nomor terakhir.

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

masukkan deskripsi gambar di sini

Roman Luštrik
sumber
6

Keduanya facet_wrapdan facet_gridjuga menerima masukan dari ifelsesebagai argumen. Jadi jika variabel yang digunakan untuk faceting adalah logis, solusinya sangat sederhana:

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

Jika variabel memiliki lebih banyak kategori, ifelsepernyataan itu perlu disarangkan .

Sebagai efek samping, ini juga memungkinkan pembuatan kelompok-kelompok yang harus dipertimbangkan dalam ggplotpanggilan.

lillemets
sumber
5

Menambahkan solusi lain yang mirip dengan @ domi dengan parsing simbol matematika, superskrip, subskrip, tanda kurung / kurung, .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}, "]"))))

Dibuat pada 2019-03-30 oleh paket reprex (v0.2.1.9000)

Tung
sumber
Lihat juga
Tung
3

Saya pikir semua solusi lain sangat membantu untuk melakukan ini, tetapi ada cara lain.

Saya berasumsi:

  • Anda telah menginstal dplyrpaket, yang memiliki mutateperintah praktis , dan
  • dataset Anda dinamai survey.

    survei%>% bermutasi (Hosp1 = Hospital1, Hosp2 = Hospital2, ........)

Perintah ini membantu Anda mengubah nama kolom, namun semua kolom lainnya disimpan.

Kemudian lakukan hal yang sama facet_wrap, Anda baik-baik saja sekarang.

son520804
sumber
maaf, itu tidak berfungsi karena juga mengubah konten kolom
Jens
3

Definisi fungsi labeller variable, valuesebagai argumen tidak akan bekerja untuk saya. Juga jika Anda ingin menggunakan ekspresi Anda perlu menggunakan lapply dan tidak bisa hanya menggunakan arr[val], karena argumen ke fungsi adalah data.frame.

Kode ini berhasil:

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)
reox
sumber
3

Karena saya belum diizinkan untuk mengomentari posting, saya memposting ini secara terpisah sebagai tambahan untuk jawaban Vince dan jawaban son520804 . Penghargaan bagi mereka.

Son520804:

menggunakan data Iris:

Saya berasumsi:
Anda telah menginstal paket dplyr, yang memiliki perintah mutate yang nyaman, dan dataset Anda bernama survey. survey %>% mutate(Hosp1 = Hospital1, Hosp2 = Hospital2,........) Perintah ini membantu Anda mengubah nama kolom, namun semua kolom lainnya disimpan. Kemudian lakukan facet_wrap yang sama, Anda baik-baik saja sekarang.

Menggunakan contoh iris Vince dan kode parsial son520804, saya melakukan ini dengan fungsi bermutasi dan mencapai solusi yang mudah tanpa menyentuh dataset asli. Caranya adalah dengan membuat vektor nama stand-in dan menggunakan mutate () di dalam pipa untuk memperbaiki nama facet sementara:

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

Dalam contoh ini Anda dapat melihat level i $ Species untuk sementara diubah menjadi nama-nama umum terkait yang terkandung dalam vektor new_names. Baris berisi

mutate(Species=new_names) %>%

dapat dengan mudah dihapus untuk mengungkapkan penamaan aslinya.

Peringatan: Ini dapat dengan mudah menyebabkan kesalahan dalam nama jika vektor new_name tidak diatur dengan benar. Mungkin akan jauh lebih bersih untuk menggunakan fungsi terpisah untuk mengganti string variabel. Ingatlah bahwa vektor new_name mungkin perlu diulang dengan cara yang berbeda agar sesuai dengan urutan dataset asli Anda. Harap periksa dua kali dan tiga kali lipat bahwa ini benar-benar tercapai.

Alexander Kielland
sumber
Mungkin sedikit lebih baik untuk digunakan: new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris')dan kemudian dalam bermutasi Anda dapat membuat kolom baru demikian:mutate(Spec = new_names[Species])
filups21
3

Ini bekerja untuk saya.

Tentukan faktor:

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

dan gunakan, di ggplot():

facet_grid( hospitals.factor[hospital] ~ . )
Hernán Castelo
sumber
2

Hanya memperluas jawaban naught101 - kredit jatuh padanya

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

Yang harus Anda lakukan adalah membuat daftar dengan pemetaan nama-ke-nama

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

dan mendefinisikan kembali plot_labeller()dengan argumen default baru:

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

Lalu:

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

Atau Anda dapat membuat fungsi khusus untuk setiap perubahan label yang ingin Anda miliki.

pengguna4786271
sumber
2

Saya memiliki cara lain untuk mencapai tujuan yang sama tanpa mengubah data yang mendasarinya:

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

Apa yang saya lakukan di atas adalah mengubah label faktor dalam bingkai data asli, dan itulah satu-satunya perbedaan dibandingkan dengan kode asli Anda.

ytu
sumber
1

Sudahkah Anda mencoba mengubah level spesifik Hospitalvektor Anda ?

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"
philiporlando
sumber
1

Saya merasa saya harus menambahkan jawaban saya untuk ini karena butuh waktu cukup lama untuk membuat ini bekerja:

Jawaban ini untuk Anda jika:

  • Anda tidak ingin mengedit data asli Anda
  • jika Anda memerlukan ekspresi ( bquote) di label dan
  • jika Anda ingin fleksibilitas dari label-nama pelabelan terpisah

Saya pada dasarnya menempatkan label dalam vektor bernama sehingga label tidak akan bingung atau beralih. The labellerekspresi mungkin bisa lebih sederhana, tapi ini setidaknya karya (perbaikan sangat menyambut). Perhatikan `(kutipan kembali) untuk melindungi faktor-segi.

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

masukkan deskripsi gambar di sini

dani
sumber
1

Solusi sederhana (dari sini ):

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)
Nick
sumber
0

Setelah berjuang sebentar, apa yang saya temukan adalah bahwa kita dapat menggunakan fct_relevel()dan fct_recode()dari forcatsdalam hubungannya untuk mengubah urutan sisi serta memperbaiki label sisi. Saya tidak yakin apakah itu didukung oleh desain, tetapi itu berhasil! Lihatlah plot di bawah ini:

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

Dibuat pada 2020-02-16 oleh paket reprex (v0.3.0)

Ashirwad
sumber