วิธีใช้ตัวแปรเพื่อระบุชื่อคอลัมน์ใน ggplot


110

ฉันมีคำสั่ง ggplot

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

ภายในฟังก์ชัน แต่ฉันต้องการใช้พารามิเตอร์ของฟังก์ชันเพื่อเลือกคอลัมน์เพื่อใช้เป็นสีและกลุ่ม คือฉันต้องการอะไรแบบนี้

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

เพื่อให้คอลัมน์ที่ใช้ใน ggplot ถูกกำหนดโดยพารามิเตอร์ เช่นสำหรับ f ("majr") เราได้รับผลของ

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

แต่สำหรับ f ("เพศ") เราได้รับผลของ

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

บางสิ่งที่ฉันลอง:

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

ไม่ทำงาน. หรือไม่

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

คำตอบ:


166

คุณสามารถใช้aes_string:

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

ตราบเท่าที่คุณส่งคอลัมน์ไปยังฟังก์ชันเป็นสตริง ( f("majr")แทนที่จะเป็นf(majr)) โปรดทราบว่าเราได้เปลี่ยนคอลัมน์อื่น ๆ"name"และ"rate"เป็นสตริง

หากคุณไม่ต้องการใช้ด้วยเหตุผลใดaes_stringคุณสามารถเปลี่ยนเป็น (ยิ่งค่อนข้างยุ่งยาก):

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

มันคุ้มค่าที่จะบอกว่าคุณไม่ควร / ทำไม่ได้aes_string(x = rates.by.groups$name...และคุณไม่จำเป็นต้องทำเพราะคุณได้ผ่านการggplot(data = rates.by.groups...โต้แย้งไปแล้ว (ปัญหาในคำถามนี้ )
smci

5
เพียงเพิ่มบันทึกเพื่อชี้ให้ผู้คนเห็นคำตอบของ Moody_Mudskipper พร้อมอัปเดตสำหรับ ggplot2 เวอร์ชัน 3.0.0
Gregor Thomas

@buncis นั่นไม่เป็นความจริงอ้าง"column_name"หรือ"column"ไม่ได้ผล
David Robinson

@DavidRobinson ขอโทษความผิดพลาดของฉันฉันไม่เห็นว่ารหัสถูกห่อไว้ในฟังก์ชันที่มีพารามิเตอร์จะลบความคิดเห็นของฉัน
buncis

"ยุ่งยาก"? การประเมินที่ไม่ได้มาตรฐานใน R เป็น "คุณลักษณะ" ที่ยุ่งยากที่สุดที่ฉันเคยพบในภาษาโปรแกรม น่าเศร้าอย่างแท้จริง
jessexknight

48

จากบันทึกประจำรุ่นของggplot2 V3.0.0:

aes () รองรับ quasiquotation เพื่อให้คุณสามารถใช้ได้ !!, !!! และ: =. สิ่งนี้จะแทนที่ aes_ () และ aes_string () ซึ่งตอนนี้เลิกใช้งานแบบซอฟต์แล้ว (แต่จะยังคงอยู่เป็นเวลานาน)

ตอนนี้วิธีสำนวนคือการแปลงเป็นสัญลักษณ์สตริงที่ตัวแปรมีโดยใช้sym()(ซึ่งเกือบจะเหมือนกับนามแฝงฐานas.name()/ as.symbol()) และยกเลิกการอ้างสิทธิ์โดยใช้!!

การจำลองข้อมูลของ OP ที่เราสามารถทำได้:

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)

หากเราต้องการป้อนชื่อดิบให้กับฟังก์ชันเราสามารถทำได้:

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

มันจะทำงานกับชื่อ aka สัญลักษณ์ AND กับสตริงตัวอักษร

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

ดังที่ไลโอเนลพูดเกี่ยวกับensym():

หมายถึงการเลียนแบบไวยากรณ์ของอาร์กิวเมนต์ที่คุณสามารถจัดหาทั้งใน LHS เช่นรายการ (bare = 1, "quoted" = 2)


หมายเหตุเกี่ยวกับ enquo()

enquo()ใส่เครื่องหมายคำพูดนิพจน์ (ไม่จำเป็นต้องเป็นสัญลักษณ์) ที่ป้อนเข้ากับอาร์กิวเมนต์มันไม่ได้แปลงสตริงลิเทอรัลเป็นสัญลักษณ์เหมือนensym()อย่างที่คิดดังนั้นจึงอาจปรับได้น้อยกว่าที่นี่ แต่เราสามารถทำได้:

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)

14
นี้tidyevalสิ่งที่เป็นที่น่ารำคาญดังนั้น เอกสารสำหรับaes()ตัวมันเองพูดถึงenquo()แต่ไม่ได้ผล และใครเคยได้ยินมาensym()ก่อน? BIG
SIGH

@Moody_Mudskipper สำหรับf2ทั้งสี่ตัวอย่างใช้งานได้และการจับชื่อคอลัมน์ในตัวแปร (เช่นaname <- "mjr"; f2(aname)) ถ้าฉันเพิ่มโค้ดเพื่อจัดการกับ data frame โดยใช้dplyrมันจะพยายามค้นหาคอลัมน์โดยใช้ชื่อตัวแปรไม่ใช่สตริงในชื่อตัวแปร ในคำอื่น ๆ ฉันจะได้รับrates.by.groups %>% group_by(!!column)...ในการทำงานและยังคงสนับสนุนการสามวิธีการเรียกf2?
steveb

1
"การจับชื่อคอลัมน์ในตัวแปรก็เช่นกัน": ไม่ล้มเหลว แต่ไม่ส่งคืนผลลัพธ์เดียวกันensymออกแบบมาเพื่อจัดการกับอาร์กิวเมนต์ที่ระบุเป็นชื่อและทนต่อคำพูดรอบตัว ฉันเชื่อว่าคุณต้องการใช้อาร์กิวเมนต์เป็นชื่อและยอมกลับไปใช้ค่านี้หากไม่พบชื่อ นี่คือสิ่งที่เกิดขึ้นจริงselectแต่ไม่ใช่กับgroup_by... เป็นไปได้ที่จะแฮ็กไปรอบ ๆ แต่ไม่ชัดเจน ถ้ามันสำคัญสำหรับคุณฉันคิดว่ามันสมควรได้รับคำถามของมันเอง
Moody_Mudskipper

@Moody_Mudskipper ขอบคุณ ฉันใช้ทั้งสองอย่างselectและgroup_byนั่นอาจเป็นปัญหา ฉันสามารถสร้างคำถามใหม่ได้ แต่ฉันต้องสร้างตัวอย่างง่ายๆและตรวจสอบว่ามีคำตอบหรือไม่ ฉันสามารถโพสต์ได้ถ้าไม่
steveb

1
วิธีใช้ !! ในกรณีfacet_grid? ใช้งานได้facet_grid(cols = vars(!!column))แต่แสดงข้อผิดพลาดด้วยfacet_grid(~ !!column)
mRiddle

15

ลองใช้aes_stringแทนaes.


5
นี่เป็นคำแนะนำที่ดี แต่คุณสามารถบอกได้ว่าทำไม? aes_string ทำให้คุณใช้ "" สำหรับตัวแปรที่ไม่ใช่และคุณใช้ตัวแปรโดยไม่ต้องอ้าง aes_string (x = "foo", y = "fee", group = variable)
mtelesha

@mtelesha อาจเป็นเพราะตัวแปรมีสตริงเป็นค่า
buncis

12

อีกทางเลือกหนึ่ง ( ggplot2 > 3.0.0) คือการใช้สรรพนามการประเมินที่เป็นระเบียบเรียบร้อย.dataเพื่อแบ่งตัวแปร / คอลัมน์ที่เลือกจากrates.by.groupsกรอบข้อมูล

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

สร้างเมื่อ 2019-04-04 โดยแพ็คเกจ reprex (v0.2.1.9000)


1

ใช้aes_stringไม่แก้ไขปัญหานี้ geom_errorbarแต่ไม่ใบหน้าปัญหาเมื่อมีการเพิ่มแถบข้อผิดพลาด ด้านล่างนี้เป็นวิธีง่ายๆ

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

โบนัสคุณยังสามารถเพิ่มแง่มุมให้กับพล็อตของคุณโดยใช้บรรทัดเหล่านี้ภายใน ggplot:

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

สคริปต์นี้ถูกแก้ไขจากโพสต์ต้นฉบับนี้: ggplot2 - แถบข้อผิดพลาดโดยใช้ฟังก์ชันที่กำหนดเอง


1

นี่เป็นตัวอย่างที่ง่ายมาก

เพียงแค่ทำสองสิ่ง

  1. เปลี่ยนสตริงให้เป็นสัญลักษณ์
  2. เพิ่ม!!เมื่อคุณใช้งาน
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.