มีวิธีจัดการกับการแบ่งขนาดและป้ายกำกับของ ggplot หรือไม่?

โดยทั่วไป ggplot ทำงานได้ดีในการสร้างตัวแบ่งและป้ายกำกับในระดับมาตราส่วน

อย่างไรก็ตาม ฉันพบว่าในพล็อตที่มีหลายแง่มุมและอาจเป็นคำสั่ง formatter= ป้ายกำกับมักจะ "หนาแน่น" เกินไปและพิมพ์ทับ เช่น ในภาพนี้:

df <- data.frame(
        fac=rep(LETTERS[1:10], 100),
        x=rnorm(1000)
)

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(formatter="percent")

ป้อนคำอธิบายรูปภาพที่นี่

ฉันรู้ว่าฉันสามารถระบุตัวแบ่งและป้ายกำกับของมาตราส่วนได้อย่างชัดเจน โดยระบุอาร์กิวเมนต์ breaks= และ scale= ให้กับ scale_x_continuous

อย่างไรก็ตาม ฉันกำลังประมวลผลข้อมูลแบบสำรวจที่มีคำถามมากมายและมีข้อผิดพลาดหลายสิบข้อ ดังนั้นจึงต้องหาวิธีดำเนินการโดยอัตโนมัติ

มีวิธีบอก ggplot ให้คำนวณตัวแบ่งและป้ายกำกับโดยอัตโนมัติแต่ให้น้อยลง เช่น จุดต่ำสุด สูงสุด และศูนย์หรือไม่

แก้ไข: ตามหลักการแล้ว ฉันไม่ต้องการระบุคะแนนต่ำสุดและสูงสุด แต่อย่างใดให้ใช้ประโยชน์จากการฝึกเครื่องชั่ง ggplot ในตัว และใช้ขีดจำกัดมาตราส่วนจากการคำนวณเริ่มต้น


person Andrie    schedule 21.03.2011    source แหล่งที่มา


คำตอบ (2)


คุณสามารถส่งผ่านอาร์กิวเมนต์ เช่น min() และ max() ในการเรียกของคุณไปยัง ggplot เพื่อระบุตัวแบ่งแบบไดนามิก ดูเหมือนว่าคุณกำลังจะใช้สิ่งนี้กับข้อมูลที่หลากหลาย ดังนั้นคุณอาจต้องการพิจารณาสรุปสิ่งนี้ให้เป็นฟังก์ชันและทำให้การจัดรูปแบบยุ่งเหยิง แต่วิธีนี้น่าจะได้ผล:

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(breaks = c(min(df$x), 0, max(df$x))
    , labels = c(paste( 100 * round(min(df$x),2), "%", sep = ""), paste(0, "%", sep = ""), paste( 100 * round(max(df$x),2), "%", sep = ""))
    )

หรือหมุนข้อความแกน x ด้วย opts(axis.text.x = theme_text(angle = 90, hjust = 0)) เพื่อสร้างสิ่งที่ต้องการ:

ป้อนคำอธิบายรูปภาพที่นี่

อัปเดต

ในเวอร์ชันล่าสุดของ ggplot2 อาร์กิวเมนต์ breaks และ labels สำหรับ scale_x_continuous ยอมรับฟังก์ชัน ดังนั้นจึงสามารถทำสิ่งต่อไปนี้ได้:

myBreaks <- function(x){
    breaks <- c(min(x),median(x),max(x))
    names(breaks) <- attr(breaks,"labels")
    breaks
}

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(breaks = myBreaks,labels = percent_format()) + 
  opts(axis.text.x = theme_text(angle = 90, hjust = 1,size = 5))
person Chase    schedule 21.03.2011
comment
@เชส ขอบคุณครับ.. ใช่ ฉันเคยคิดที่จะทำเช่นนี้แล้ว แต่มันไม่เหมาะ เหตุผลก็คือ ข้อมูลอาจเป็นเปอร์เซ็นต์ จำนวนผู้ตอบแบบสอบถาม คะแนน t-stat หรืออะไรก็ตาม การคำนวณขนาดที่ใกล้ที่สุดอาจเป็นตัวเลือก แต่จริงๆ แล้วสิ่งที่ฉันต้องการทำคือใช้สเกลที่ ggplot ฝึกฝน จากนั้นซ่อนป้ายกำกับระหว่างจุดสิ้นสุด กล่าวอีกนัยหนึ่ง บางครั้งฉันต้องการให้ส่วนบนของสเกลเป็น (ตัวอย่าง) 60% ฉันหวังว่านี่จะสมเหตุสมผล - person Andrie; 21.03.2011
comment
@Andrie - เข้าใจแล้ว สิ่งที่คุณต้องการจริงๆ ที่นี่คือฟังก์ชันที่ตีความประเภทของข้อมูลที่แสดงบนแกน x (เปอร์เซ็นต์ จำนวนนับ ฯลฯ...) และปรับเปลี่ยนสเกลตามนั้น ใช่ไหม? คุณสามารถใช้ class() ในคอลัมน์เพื่อช่วยแจ้งเรื่องนี้ได้หรือไม่ หรือข้อมูล / metdata อื่น ๆ ที่แจ้งว่าคุณกำลังวางแผนอะไรกันแน่? การเขียนฟังก์ชันเล็กๆ เพื่อสร้างเวกเตอร์ของตัวแบ่งและป้ายกำกับเพื่อส่งผ่านไปยัง scale_x_continuous() ไม่ใช่เรื่องยากเกินไป โดยสมมติว่าคุณมีข้อมูลบางอย่างเพื่อแจ้งว่าจะจัดรูปแบบอะไรและอย่างไร - person Chase; 21.03.2011
comment
@Chase ฉันหวังว่าจะมีคนให้แนวทางทั่วไปมากกว่านี้ ตัวอย่างเช่น เมื่อทำงานกับ facets และ free scales เช่น facet_grid(~fac, scales=free) โดยทั่วไปจุดพักสูงและต่ำจะแตกต่างกันสำหรับแต่ละด้าน ดังนั้นสิ่งที่ฉันติดตามจริงๆ คือการระงับป้ายกำกับโดยไม่ระบุช่วงพัก - person Andrie; 21.03.2011
comment
@Andrie บางทีคุณสามารถจัดเตรียมชุดข้อมูลตัวอย่างที่อัปเดตซึ่งแสดงให้เห็นถึงปัญหาของคุณได้ดีขึ้น เท่าที่ผมบอกได้ คุณมีปัญหาที่แตกต่างกันอย่างน้อยสองประเด็น 1. การโอเวอร์พล็อตแกนสเกล 2. ใช้โค้ดอันเดียวกันเพื่อนำเสนอข้อมูลเดียวกันในสภาพแสงที่แตกต่างกัน คุณสามารถจัดการกับ overplotting ด้วยบางอย่างเช่น ... + opts(axis.text.x = theme_text(angle = 90, hjust = 0)) หากคุณต้องการก้าวไปไกลกว่าปัญหาการจัดรูปแบบ ฉันคิดว่าคุณจะต้องเขียนฟังก์ชันของคุณเองเพื่อส่งพารามิเตอร์ไปที่ labels() และ breaks() - person Chase; 22.03.2011
comment
+1 สำหรับการแนะนำการเปลี่ยนมุมของข้อความและขนาดของข้อความ สิ่งนี้จะช่วยตอบสนองความต้องการในการนำเสนอของฉันได้ทันที - person Andrie; 22.03.2011
comment
+1.5 สำหรับการยอมรับ เพื่อแจ้งให้ทราบ Hadley Wickham ตอบในฟอรัมอื่นว่าสิ่งที่ฉันต้องการทำนั้นไม่ใช่เรื่องง่ายที่จะทำในขณะนี้ แต่ในอนาคตอันใกล้นี้ เราจะสามารถควบคุมตัวแบ่งและเครื่องหมายถูกได้มากขึ้น - person Andrie; 22.03.2011

แพ็คเกจ scales มีฟังก์ชัน breaks_* และ label_* หลายฟังก์ชันซึ่งส่งคืนฟังก์ชัน (การปิด) ที่ใช้โดย ggplot ดังนั้น คุณสามารถเขียน wrapper สำหรับสิ่งเหล่านี้เพื่อแก้ไขเอาต์พุตได้

ตัวอย่างเช่น:

library(ggplot2)

# Compute the list of breaks using original_func,
# then remove any of these that occur in remove_list
remove_breaks <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    original_result[!(original_result %in% remove_list)]
  }
}

# Compute the list of labels using original_func,
# then remove any of these that occur in remove_list
remove_labels <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    replace(original_result, original_result %in% remove_list, '')
  }
}

# Original plot
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto())

# Remove some breaks from the x-axis, and remove some labels from the y-axis
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = remove_breaks(scales::breaks_pretty(9), seq(3,6)),
                     minor_breaks = remove_breaks(scales::breaks_pretty(18), seq(3,6,0.5)),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = remove_labels(scales::label_number_auto(), seq(20, 30)))

แน่นอนว่า ด้วยฟังก์ชัน remove_breaks และ remove_labels อย่างง่ายของฉัน คุณยังคงต้องระบุค่าที่จะลบ แต่คุณสามารถแก้ไขค่าเหล่านี้เป็นค่าที่ลบค่าสูงสุดและต่ำสุด ลบค่าใดๆ ในช่วงที่ระบุ ฯลฯ ได้อย่างง่ายดาย

person Tim Goodman    schedule 18.03.2020
comment
เขียนตอบก่อนจะสังเกตว่าคำถามอายุเท่าไหร่ ????. - person Tim Goodman; 18.03.2020