แสดง% แทนที่จะนับในแผนภูมิของตัวแปรเด็ดขาด


170

ฉันกำลังวางแผนตัวแปรเด็ดขาดและแทนที่จะแสดงจำนวนสำหรับค่าหมวดหมู่แต่ละรายการ

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

ฉันกำลังทดลองกับสิ่งที่ชอบ

qplot(mydataf) +
  stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
  scale_y_continuous(formatter = "percent")

แต่ฉันต้องใช้มันอย่างไม่ถูกต้องเนื่องจากฉันพบข้อผิดพลาด

ในการทำซ้ำการตั้งค่าได้ง่ายนี่คือตัวอย่างง่าย ๆ :

mydata <- c ("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc");
mydataf <- factor(mydata);
qplot (mydataf); #this shows the count, I'm looking to see % displayed.

ในกรณีจริงฉันอาจใช้ggplotแทนqplotแต่วิธีที่ถูกต้องในการใช้stat_binยังคงหลบเลี่ยงฉันอยู่

ฉันได้ลองวิธีทั้งสี่นี้แล้ว:

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

แต่ทั้ง 4 ให้:

Error: ggplot2 doesn't know how to deal with data of class factor

ข้อผิดพลาดเดียวกันปรากฏขึ้นสำหรับกรณีง่าย ๆ ของ

ggplot (data=mydataf, aes(levels(mydataf))) +
  geom_bar()

ดังนั้นจึงเป็นเรื่องที่ชัดเจนเกี่ยวกับการggplotโต้ตอบกับเวกเตอร์เดียว ฉันเกาหัวของฉัน googling สำหรับข้อผิดพลาดที่ให้เพียงครั้งเดียวผล


2
ข้อมูลควรเป็นกรอบข้อมูลไม่ใช่ปัจจัยเปล่า
hadley

1
การเพิ่มความคิดเห็นของ Hadley การแปลงข้อมูลของคุณเป็น data frame โดยใช้ mydataf = data.frame (mydataf) และเปลี่ยนชื่อเป็นชื่อ (mydataf) = foo จะทำเคล็ดลับ
Ramnath

คำตอบ:


221

เนื่องจากคำตอบนี้มีการเปลี่ยนแปลงบางอย่างที่มีความหมายกับggplotไวยากรณ์ สรุปการอภิปรายในความคิดเห็นด้านบน:

 require(ggplot2)
 require(scales)

 p <- ggplot(mydataf, aes(x = foo)) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        ## version 3.0.0
        scale_y_continuous(labels=percent)

นี่คือตัวอย่างที่ทำซ้ำได้โดยใช้mtcars:

 ggplot(mtcars, aes(x = factor(hp))) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        scale_y_continuous(labels = percent) ## version 3.0.0

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

ปัจจุบันคำถามนี้ได้รับความนิยมเป็นอันดับ 1 ใน google สำหรับ 'ggplot count เทียบกับฮิสโตแกรมนับร้อยละ' ดังนั้นหวังว่านี่จะช่วยกลั่นกรองข้อมูลทั้งหมดที่อยู่ในความคิดเห็นเกี่ยวกับคำตอบที่ได้รับการยอมรับ

หมายเหตุ:หากhpไม่ได้ตั้งค่าเป็นปัจจัย ggplot จะส่งคืน:

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


12
ขอบคุณสำหรับคำตอบนี้ ความคิดเกี่ยวกับวิธีการทำระดับปัญญา?
WAF

3
ในฐานะ. @ WAF แนะนำคำตอบนี้ไม่ทำงานกับข้อมูลประกอบ ดูความคิดเห็นของ @ Erwan ในstackoverflow.com/questions/22181132/…
LeeZamparo

1
คุณอาจต้องนำหน้าpercentด้วยแพ็คเกจที่มาจากข้างต้นเพื่อให้ทำงานได้ (ฉันทำ) ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins

เพื่อหลีกเลี่ยงการใช้ facets ใช้geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))แทน แต่ละด้านควรรวมถึง 100%
JWilliman

ไม่ใช่ตัวแปรที่มี ".. " ล้อมรอบพวกเขาถูกแทนที่ด้วยคำสั่ง stat () -? ggplot2.tidyverse.org/reference/stat.html
แมกนัส

58

รหัสที่แก้ไขนี้ควรใช้งานได้

p = ggplot(mydataf, aes(x = foo)) + 
    geom_bar(aes(y = (..count..)/sum(..count..))) + 
    scale_y_continuous(formatter = 'percent')

หากข้อมูลของคุณมี NA และคุณไม่ต้องการให้รวมอยู่ในพล็อตให้ส่ง na.omit (mydataf) เป็นอาร์กิวเมนต์สำหรับ ggplot

หวังว่านี่จะช่วยได้


37
โปรดทราบว่าใน ggplot2 เวอร์ชัน 0.9.0 formatterอาร์กิวเมนต์จะไม่ทำงานอีกต่อไป labels = percent_format())แต่คุณจะต้องการสิ่งที่ต้องการ
joran

25
และด้วย 0.9.0 คุณจะต้องโหลดscalesไลบรารีก่อนใช้percent_format()มิฉะนั้นจะไม่สามารถใช้งานได้ 0.9.0 จะไม่โหลดแพ็คเกจสนับสนุนโดยอัตโนมัติอีกต่อไป
Andrew

1
? stat_binดู ggplot2มันแสดงให้เห็นว่าสิ่งที่คอลัมน์เพิ่มเติมจะมีการเพิ่มกรอบข้อมูลโดย ..variable..คอลัมน์พิเศษทั้งหมดอยู่ในรูปแบบ
Ramnath

1
มันสมเหตุสมผลไหมที่จะแทนที่aes(y = (..count..)/sum(..count..))ด้วยง่ายๆaes(y = ..density..)? ภาพนั้นให้ภาพที่คล้ายกันมาก (แต่ก็ยังแตกต่างกัน)
Alexander Kosenkov

6
ใน ggplot 0.9.3.1.0 คุณจะต้องโหลดscalesไลบรารีก่อนจากนั้นใช้scale_y_continuous(labels=percent)ตามที่กล่าวไว้ในเอกสาร
adilapapaya


37

เมื่อวันที่มีนาคม 2560 กับggplot22.2.1 ฉันคิดว่าคำอธิบายที่ดีที่สุดใน Hadley Wickham's R สำหรับหนังสือวิทยาศาสตร์ข้อมูล:

ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))

stat_countคำนวณสองตัวแปร: countใช้เป็นค่าเริ่มต้น แต่คุณสามารถเลือกที่จะใช้propซึ่งแสดงสัดส่วน


3
นี่คือคำตอบที่ดีที่สุดของเดือนมิถุนายน 2017 ทำงานร่วมกับการเติมตามกลุ่มและเผชิญกับ
Skumin

1
ด้วยเหตุผลบางอย่างสิ่งนี้ไม่อนุญาตให้ฉันใช้การfillแมป (ไม่มีข้อผิดพลาดเกิดขึ้น แต่ไม่มีการเพิ่มสีเติม)
Max Candocia

@ MaxCandocia ฉันต้องลบออกgroup = 1เพื่อรับการแมปเติม อาจช่วยได้
Tjebo

1
ถ้าฉันลบgroupพารามิเตอร์มันจะไม่แสดงเปอร์เซ็นต์ที่เหมาะสมเนื่องจากทุกอย่างอยู่ในกลุ่มของตัวเองสำหรับค่า x แต่ละค่า
Max Candocia

20

หากคุณต้องการเปอร์เซ็นต์บนแกน y และติดป้ายบนแถบ:

library(ggplot2)
library(scales)
ggplot(mtcars, aes(x = as.factor(am))) +
  geom_bar(aes(y = (..count..)/sum(..count..))) +
  geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.25) +
  scale_y_continuous(labels = percent) +
  labs(title = "Manual vs. Automatic Frequency", y = "Percent", x = "Automatic Transmission")

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

เมื่อเพิ่มป้ายชื่อบาร์คุณอาจต้องการละเว้นแกน y สำหรับแผนภูมิที่สะอาดกว่าโดยเพิ่มไปที่ท้าย:

  theme(
        axis.text.y=element_blank(), axis.ticks=element_blank(),
        axis.title.y=element_blank()
  )

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


6

หากคุณต้องการเปอร์เซ็นต์ป้ายกำกับแต่เป็น Ns จริงบนแกน y ลองสิ่งนี้:

    library(scales)
perbar=function(xx){
      q=ggplot(data=data.frame(xx),aes(x=xx))+
      geom_bar(aes(y = (..count..)),fill="orange")
       q=q+    geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen") 
      q
    }
    perbar(mtcars$disp)

6

นี่เป็นวิธีแก้ปัญหาสำหรับข้อมูลประกอบ (คำตอบที่ยอมรับโดย @Andrew ไม่ทำงานในกรณีนี้) แนวคิดคือการคำนวณค่าเปอร์เซ็นต์โดยใช้ dplyr แล้วใช้ geom_col เพื่อสร้างพล็อต

library(ggplot2)
library(scales)
library(magrittr)
library(dplyr)

binwidth <- 30

mtcars.stats <- mtcars %>%
  group_by(cyl) %>%
  mutate(bin = cut(hp, breaks=seq(0,400, binwidth), 
               labels= seq(0+binwidth,400, binwidth)-(binwidth/2)),
         n = n()) %>%
  group_by(cyl, bin) %>%
  summarise(p = n()/n[1]) %>%
  ungroup() %>%
  mutate(bin = as.numeric(as.character(bin)))

ggplot(mtcars.stats, aes(x = bin, y= p)) +  
  geom_col() + 
  scale_y_continuous(labels = percent) +
  facet_grid(cyl~.)

นี่คือพล็อต:

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


3

โปรดทราบว่าหากตัวแปรของคุณต่อเนื่องคุณจะต้องใช้ geom_histogram () เนื่องจากฟังก์ชันจะจัดกลุ่มตัวแปรตาม "ถังขยะ"

df <- data.frame(V1 = rnorm(100))

ggplot(df, aes(x = V1)) +  
  geom_histogram(aes(y = (..count..)/sum(..count..))) 

# if you use geom_bar(), with factor(V1), each value of V1 will be treated as a
# different category. In this case this does not make sense, as the variable is 
# really continuous. With the hp variable of the mtcars (see previous answer), it 
# worked well since hp was not really continuous (check unique(mtcars$hp)), and one 
# can want to see each value of this variable, and not to group it in bins.
ggplot(df, aes(x = factor(V1))) +  
  geom_bar(aes(y = (..count..)/sum(..count..))) 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.