Hiển thị% thay vì đếm trong biểu đồ của các biến phân loại


170

Tôi đang vẽ một biến phân loại và thay vì hiển thị số lượng cho từng giá trị danh mục.

Tôi đang tìm cách ggplotđể hiển thị phần trăm giá trị trong danh mục đó. Tất nhiên, có thể tạo một biến khác với tỷ lệ phần trăm và âm mưu được tính toán, nhưng tôi phải thực hiện vài chục lần và tôi hy vọng sẽ đạt được điều đó trong một lệnh.

Tôi đã thử nghiệm một cái gì đó như

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

nhưng tôi phải sử dụng nó không đúng, vì tôi gặp lỗi.

Để dễ dàng tái tạo thiết lập, đây là một ví dụ đơn giản:

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.

Trong trường hợp thực tế, có lẽ tôi sẽ sử dụng ggplotthay vì qplot, nhưng cách sử dụng stat_bin đúng cách vẫn khiến tôi lảng tránh.

Tôi cũng đã thử bốn cách tiếp cận sau:

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

nhưng cả 4 đều cho:

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

Lỗi tương tự xuất hiện cho trường hợp đơn giản là

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

Vì vậy, rõ ràng một cái gì đó về cách ggplottương tác với một vectơ duy nhất. Tôi đang gãi đầu, googling cho lỗi đó cho một kết quả duy nhất .


2
Dữ liệu phải là khung dữ liệu, không phải là yếu tố trần.
hadley

1
thêm vào nhận xét của hadley, chuyển đổi dữ liệu của bạn thành khung dữ liệu bằng mydataf = data.frame (mydataf) và đổi tên thành tên (mydataf) = foo sẽ thực hiện thủ thuật
Ramnath

Câu trả lời:


221

Vì điều này đã được trả lời, đã có một số thay đổi có ý nghĩa đối với ggplotcú pháp. Tóm tắt các cuộc thảo luận trong các ý kiến ​​trên:

 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)

Đây là một ví dụ có thể tái tạo bằng cách sử dụng mtcars:

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

nhập mô tả hình ảnh ở đây

Câu hỏi này hiện đang là câu hỏi số 1 trên google về 'số lượng ggplot so với biểu đồ tỷ lệ phần trăm', vì vậy, hy vọng điều này sẽ giúp chắt lọc tất cả thông tin hiện đang được lưu trữ trong các nhận xét về câu trả lời được chấp nhận.

Lưu ý: Nếu hpkhông được đặt làm yếu tố, ggplot trả về:

nhập mô tả hình ảnh ở đây


12
Cảm ơn câu trả lời này. Bất kỳ ý tưởng về làm thế nào để làm điều đó khôn ngoan?
WAF

3
Như. @ WAF gợi ý, câu trả lời này không hoạt động với dữ liệu mặt. Xem bình luận của @ Erwan trong stackoverflow.com/questions/22181132/ từ
LeeZamparo

1
Bạn có thể cần phải thêm tiền tố percentvào gói để nó hoạt động ở trên (tôi đã làm). ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins

Để có được xung quanh sử dụng các khía cạnh sử dụng geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))thay thế. Mỗi khía cạnh nên tổng hợp đến 100%.
JWilliman

Không phải các biến có ".." xung quanh chúng được thay thế bằng lệnh stat () - sao? ggplot2.tidyverse.org/reference/stat.html
Magnus

58

mã sửa đổi này sẽ hoạt động

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

nếu dữ liệu của bạn có NA và bạn không muốn đưa chúng vào cốt truyện, hãy chuyển na.omit (mydataf) làm đối số cho ggplot.

hi vọng điêu nay co ich.


37
Lưu ý rằng trong ggplot2 phiên bản 0.9.0, formatterđối số sẽ không còn hoạt động. Thay vào đó, bạn sẽ muốn một cái gì đó như labels = percent_format()).
joran

25
Và với 0.9.0, bạn sẽ cần tải scalesthư viện trước khi sử dụng percent_format(), nếu không nó sẽ không hoạt động. 0.9.0 không tự động tải các gói hỗ trợ nữa.
Andrew

1
Xem ? stat_bin. Nó cho thấy những cột bổ sung nào được thêm vào khung dữ liệu ggplot2. Tất cả các cột thêm có dạng ..variable...
Ramnath

1
Liệu nó có ý nghĩa để thay thế aes(y = (..count..)/sum(..count..))bằng đơn giản aes(y = ..density..)? Nhìn trực quan, nó cho hình ảnh rất giống (nhưng vẫn khác)
Alexander Kosenkov

6
Trong ggplot 0.9.3.1.0, trước tiên bạn sẽ muốn tải scalesthư viện, sau đó sử dụng scale_y_continuous(labels=percent)như được đề cập trong tài liệu
adilapapaya

49

Với ggplot2 phiên bản 2.1.0, nó là

+ scale_y_continuous(labels = scales::percent)

37

Kể từ tháng 3 năm 2017, với ggplot22.2.1, tôi nghĩ rằng giải pháp tốt nhất được giải thích trong Hadley Wickham's R cho cuốn sách khoa học dữ liệu:

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

stat_countTính hai biến: countđược sử dụng theo mặc định, nhưng bạn có thể chọn sử dụng prophiển thị tỷ lệ.


3
Đây là câu trả lời tốt nhất kể từ tháng 6 năm 2017, hoạt động với việc điền theo nhóm và với khía cạnh.
Skumin

1
Vì một số lý do, điều này không cho phép tôi sử dụng fillánh xạ (không có lỗi nào được đưa ra, nhưng không có màu tô nào được thêm vào).
Max Candocia

@MaxCandocia Tôi phải xóa group = 1để có được ánh xạ điền. có lẽ nó giúp
Tjebo

1
Tuy nhiên, nếu tôi loại bỏ grouptham số, nó sẽ không hiển thị tỷ lệ phần trăm phù hợp, vì mọi thứ thuộc về nhóm riêng của nó cho mỗi giá trị x duy nhất.
Max Candocia

20

Nếu bạn muốn tỷ lệ phần trăm trên trục y được gắn nhãn trên các thanh:

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

nhập mô tả hình ảnh ở đây

Khi thêm nhãn thanh, bạn có thể bỏ qua trục y cho biểu đồ sạch hơn, bằng cách thêm vào cuối:

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

nhập mô tả hình ảnh ở đây


6

Nếu bạn muốn nhãn phần trăm nhưng Ns thực tế trên trục y, hãy thử điều nà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

Đây là một cách giải quyết cho dữ liệu mặt. (Câu trả lời được chấp nhận bởi @Andrew không hoạt động trong trường hợp này.) Ý tưởng là tính giá trị phần trăm bằng cách sử dụng dplyr và sau đó sử dụng geom_col để tạo cốt truyện.

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

Đây là cốt truyện:

nhập mô tả hình ảnh ở đây


3

Lưu ý rằng nếu biến của bạn là liên tục, bạn sẽ phải sử dụng geom_histogram (), vì hàm sẽ nhóm biến đó theo "thùng".

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..))) 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.