Cara menggunakan variabel untuk menentukan nama kolom di ggplot

106

Saya memiliki perintah ggplot

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

di dalam suatu fungsi. Tapi saya ingin bisa menggunakan parameter fungsi untuk memilih kolom yang akan digunakan sebagai warna dan grup. Yaitu saya ingin sesuatu seperti ini

f <- function( column ) {
    ...
    ggplot( rates.by.groups, aes(x=name, y=rate, colour= ??? , group=??? ) )
}

Sehingga kolom yang digunakan pada ggplot ditentukan oleh parameter. Misalnya untuk f ("majr") kita mendapatkan efek

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

tapi untuk f ("gender") kita mendapatkan efek

  ggplot( rates.by.groups, aes(x=name, y=rate, colour=gender, group=gender) )

Beberapa hal yang saya coba:

ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ) )

tidak bekerja. Tidak juga

e <- environment() 
ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ), environment=e )
Theodore Norvell
sumber

Jawaban:

162

Anda dapat menggunakan aes_string:

f <- function( column ) {
    ...
    ggplot( rates.by.groups, aes_string(x="name", y="rate", colour= column,
                                        group=column ) )
}

selama Anda meneruskan kolom ke fungsi sebagai string ( f("majr")bukan f(majr)). Perhatikan juga bahwa kami mengubah kolom lain, "name"dan "rate", menjadi string.

Jika karena alasan apa pun Anda tidak ingin menggunakan aes_string, Anda dapat mengubahnya menjadi (yang agak lebih rumit):

    ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
                                        group=get(column) ) )
David Robinson
sumber
Patut dikatakan bahwa Anda tidak boleh / tidak dapat melakukannya aes_string(x = rates.by.groups$name..., dan bagaimanapun Anda tidak perlu melakukannya karena Anda sudah menyampaikan ggplot(data = rates.by.groups...argumen. (Masalah dalam pertanyaan ini )
smci
3
Hanya menambahkan catatan untuk mengarahkan orang-orang ke jawaban Moody_Mudskipper dengan pembaruan untuk ggplot2 versi 3.0.0
Gregor Thomas
@buncis Itu tidak benar, mengutip "column_name"atau "column"tidak akan berhasil
David Robinson
@DavidRobinson maaf kesalahan saya, saya tidak melihat kode dibungkus pada fungsi dengan parameter, akan menghapus komentar saya
buncis
"merepotkan"? Evaluasi non-standar di R ironisnya adalah "fitur" paling rumit yang pernah saya temui dalam bahasa pemrograman. Benar-benar menjengkelkan.
jessexknight
45

Dari catatan rilis dari ggplot2 V3.0.0:

aes () sekarang mendukung quasiquotation sehingga Anda dapat menggunakan !!, !!!, dan: =. Ini menggantikan aes_ () dan aes_string () yang sekarang sudah tidak digunakan lagi (tetapi akan tetap ada untuk waktu yang lama).

Cara idiomatik sekarang adalah mengonversi ke simbol string yang berisi variabel, menggunakan sym()(yang hampir sama dengan alias basis as.name()/ as.symbol()), dan menghapusnya menggunakan!!

Mensimulasikan data OP dapat kita lakukan:

library(tidyverse)
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4,4,5)],
  gender = c("M","F","F")
)

f <- function(column) {
  column <- sym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

f("gender")
f("mjr")
x <- "gender"
f(x)

Jika kita lebih suka memberi nama mentah ke fungsi yang bisa kita lakukan:

f2 <- function(column) {
  column <- ensym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

Ini akan bekerja dengan nama alias simbol DAN dengan string literal

f2(gender)
f2(mjr)
f2("gender")
f2("mjr")

Seperti yang dikatakan Lionel tentang ensym():

itu dimaksudkan untuk meniru sintaks argumen di mana Anda dapat memasukkan keduanya di LHS, misalnya daftar (telanjang = 1, "dikutip" = 2)


Catatan tentang enquo()

enquo()mengutip ekspresi (tidak harus simbol) yang dimasukkan ke argumen, itu tidak mengubah string literal menjadi simbol seperti yang ensym()dilakukan sehingga mungkin kurang diadaptasi di sini, tetapi kita bisa melakukan:

f3 <- function(column) {
  column <- enquo(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()
}

f3(gender)
f2(mjr)
Moody_Mudskipper
sumber
12
Ini tidyeval hal begitu menjengkelkan. Dokumentasi untuk aes()dirinya sendiri berbicara tentang enquo()tetapi tidak berhasil. Dan siapa yang pernah dengar ensym()sebelumnya? BIG
SIGH
@Moody_Mudskipper Untuk f2, keempat contoh bekerja, dan begitu juga dengan menangkap nama kolom dalam variabel (yaitu aname <- "mjr"; f2(aname)). Jika saya menambahkan kode untuk memanipulasi bingkai data yang menggunakannya dplyrmencoba untuk menemukan kolom menggunakan nama variabel dan bukan string dalam nama variabel. Dengan kata lain, bagaimana cara saya berangkat rates.by.groups %>% group_by(!!column)...kerja dan masih mendukung ketiga cara menelepon f2?
steveb
1
"begitu juga dengan menangkap nama kolom dalam sebuah variabel": tidak gagal tetapi tidak mengembalikan hasil yang sama, ensymdirancang untuk menangani argumen yang diberikan sebagai nama, dan mentolerir tanda kutip di sekitarnya. Saya yakin Anda ingin memperlakukan argumen tersebut sebagai sebuah nama, dan menggunakan kembali nilainya jika nama tersebut tidak ditemukan. Ini sebenarnya yang terjadi dengan select, tetapi tidak dengan group_by... Mungkin saja untuk meretasnya tetapi tidak jelas. Jika itu penting bagi Anda, saya pikir itu akan pantas mendapatkan pertanyaannya sendiri.
Moody_Mudskipper
@Moodyfoody Terima kasih. Saya menggunakan keduanya selectdan group_bysepertinya itulah masalahnya. Saya dapat membuat pertanyaan baru, tetapi saya perlu memberikan contoh sederhana dan memeriksa apakah sudah terjawab. Saya dapat mempostingnya jika tidak.
steveb
Cara Penggunaan !! dalam kasus facet_grid? Ia bekerja dengan facet_grid(cols = vars(!!column))tetapi facet_grid(~ !!column)
memunculkan
14

Coba gunakan, aes_stringbukan aes.

MDe
sumber
5
Ini adalah nasihat yang bagus tetapi dapatkah Anda memberi tahu mereka alasannya? aes_string membuat Anda menggunakan "" untuk non-variabel dan Anda menggunakan variabel unquotes. aes_string (x = "foo", y = "fee", group = variable)
mtelesha
@mtelesha mungkin karena variabel memiliki string sebagai nilainya
buncis
10

Opsi lain ( ggplot2 > 3.0.0) adalah menggunakan kata ganti evaluasi rapi .datauntuk memotong variabel / kolom yang dipilih dari rates.by.groupsbingkai data.

library(ggplot2)
theme_set(theme_classic(base_size = 14))

# created by @Moody_Mudskipper
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4, 4, 5)],
  gender = c("M", "F", "F")
)

f1 <- function(df, column) {
  gg <- ggplot(df, 
         aes(x = name, 
             y = rate, 
             fill  = .data[[column]], 
             group = .data[[column]])) +
    geom_col() +
    labs(fill = column)
  return(gg)
}

plot_list <- lapply(list("gender", "mjr"), function(x){ f1(rates.by.groups, x) })
plot_list
#> [[1]]

#> 
#> [[2]]

# combine all plots
library(egg)
ggarrange(plots = plot_list,
          nrow = 2,
          labels = c('A)', 'B)'))

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

Tung
sumber
1

Menggunakan aes_stringmemang memperbaiki masalah ini, tetapi menghadapi masalah saat menambahkan bilah kesalahan geom_errorbar. Di bawah ini adalah solusi sederhana.

#Identify your variables using the names of your columns indie your dataset
 xaxis   <- "Independent"   
 yaxis   <- "Dependent"
 sd      <- "error"

#Specify error bar range (in 'a-b' not 'a'-'b')
 range   <- c(yaxis, sd)                                #using c(X, y) allows use of quotation marks inside formula
 yerrbar <- aes_string(ymin=paste(range, collapse='-'), 
                       ymax=paste(range, collapse='+'))


#Build the plot
  ggplot(data=Dataset, aes_string(x=xaxis, y=yaxis)) +
    geom_errorbar(mapping=yerrbar, width=15, colour="#73777a", size = 0.5) +
    geom_point   (shape=21)

Bonus, Anda juga dapat menambahkan faset ke plot Anda menggunakan garis-garis ini di dalam ggplot:

facet_grid(formula(paste(Variable1, "~", Variable2)))

Skrip ini telah diubah dari posting asli ini: ggplot2 - Bilah kesalahan menggunakan fungsi khusus

Marty999
sumber
0

Inilah contoh yang sangat sederhana.

Lakukan dua hal

  1. Ubah string menjadi simbol
  2. Tambahkan !!saat Anda menggunakannya
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
stevec
sumber