Tampilkan% alih-alih hitungan dalam bagan variabel kategorikal


171

Saya merencanakan variabel kategori dan bukannya menunjukkan jumlah untuk setiap nilai kategori.

Saya mencari cara ggplotuntuk menampilkan persentase nilai dalam kategori itu. Tentu saja, dimungkinkan untuk membuat variabel lain dengan persentase yang dihitung dan plot yang satu, tetapi saya harus melakukannya beberapa kali dan saya berharap untuk mencapai itu dalam satu perintah.

Saya sedang bereksperimen dengan sesuatu seperti

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

tapi saya harus salah menggunakannya, karena saya mendapat kesalahan.

Untuk mereproduksi pengaturan dengan mudah, berikut ini contoh sederhana:

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.

Dalam kasus yang sebenarnya, saya mungkin akan menggunakan ggplotalih-alih qplot, tetapi cara yang tepat untuk menggunakan stat_bin masih menghindari saya.

Saya juga sudah mencoba empat pendekatan ini:

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

tapi semua 4 memberi:

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

Kesalahan yang sama muncul untuk kasus sederhana

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

jadi jelas sesuatu tentang bagaimana ggplotberinteraksi dengan satu vektor. Aku menggaruk-garuk kepalaku, mencari kesalahan di Google hanya memberikan satu hasil .


2
Data harus menjadi kerangka data, bukan faktor telanjang.
hadley

1
menambahkan komentar hadley, mengubah data Anda menjadi bingkai data menggunakan mydataf = data.frame (mydataf), dan mengubah nama itu menjadi nama (mydataf) = foo akan melakukan trik
Ramnath

Jawaban:


222

Karena ini dijawab, ada beberapa perubahan yang berarti pada ggplotsintaksis. Ringkas diskusi dalam komentar di atas:

 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)

Berikut ini contoh yang dapat direproduksi menggunakan mtcars:

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

masukkan deskripsi gambar di sini

Pertanyaan ini saat ini menjadi hit # 1 di google untuk 'jumlah ggplot vs persentase histogram' sehingga mudah-mudahan ini membantu menyaring semua informasi yang saat ini disimpan di komentar pada jawaban yang diterima.

Catatan: Jika hptidak ditetapkan sebagai faktor, ggplot mengembalikan:

masukkan deskripsi gambar di sini


12
Terima kasih atas jawaban ini. Adakah ide tentang bagaimana melakukannya di kelas?
WAF

3
Seperti. @ WAF sarankan, jawaban ini tidak berfungsi dengan data faceted. Lihat komentar @ Erwan di stackoverflow.com/questions/22181132/…
LeeZamparo

1
Anda mungkin perlu awalan percentdengan paket itu dari untuk mendapatkan di atas berfungsi (saya lakukan). ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins

Untuk menyiasati penggunaan aspek, gunakan geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))saja. Setiap segi harus berjumlah 100%.
JWilliman

Bukankah variabel dengan ".." di sekitar mereka diganti dengan perintah stat () -? ggplot2.tidyverse.org/reference/stat.html
Magnus

58

kode yang dimodifikasi ini harus berfungsi

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

jika data Anda memiliki NAS dan Anda tidak ingin mereka dimasukkan dalam plot, kirimkan na.omit (mydataf) sebagai argumen ke ggplot.

semoga ini membantu.


37
Perhatikan bahwa dalam ggplot2 versi 0.9.0 formatterargumen tidak akan berfungsi lagi. Sebaliknya, Anda akan menginginkan sesuatu seperti labels = percent_format()).
joran

25
Dan dengan 0.9.0 Anda harus memuat scalesperpustakaan sebelum menggunakan percent_format(), jika tidak maka tidak akan berfungsi. 0.9.0 tidak secara otomatis memuat paket pendukung lagi.
Andrew

1
Lihat ? stat_bin. Itu menunjukkan apa kolom tambahan ditambahkan ke bingkai data oleh ggplot2. Semua kolom tambahan berbentuk ..variable...
Ramnath

1
Apakah masuk akal untuk mengganti aes(y = (..count..)/sum(..count..))dengan sederhana aes(y = ..density..)? Secara visual itu memberikan gambar yang sangat mirip (tapi masih berbeda)
Alexander Kosenkov

6
Di ggplot 0.9.3.1.0, Anda ingin memuat scalesperpustakaan terlebih dahulu , kemudian digunakan scale_y_continuous(labels=percent)seperti yang disebutkan dalam dokumen
adilapapaya


37

Pada Maret 2017, dengan ggplot22.2.1 saya pikir solusi terbaik dijelaskan dalam Hadley Wickham's R untuk buku ilmu data:

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

stat_countmenghitung dua variabel: countdigunakan secara default, tetapi Anda dapat memilih untuk menggunakan propyang menunjukkan proporsi.


3
Ini adalah jawaban terbaik per Juni 2017, bekerja dengan mengisi dengan grup dan dengan faceting.
Skumin

1
Untuk beberapa alasan ini tidak memungkinkan saya untuk menggunakan fillpemetaan (tidak ada kesalahan yang dilemparkan, tetapi tidak ada warna isian yang ditambahkan).
Max Candocia

@ Maxcandocia saya harus menghapus group = 1untuk mendapatkan pemetaan isi. mungkin itu membantu
Tjebo

1
Jika saya menghapus groupparameter, itu tidak menunjukkan persentase yang tepat, karena semuanya milik grup sendiri untuk setiap nilai x unik.
Max Candocia

20

Jika Anda ingin persentase pada sumbu y dan diberi label pada bilah:

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

masukkan deskripsi gambar di sini

Saat menambahkan label batang, Anda mungkin ingin menghilangkan sumbu y untuk bagan yang lebih bersih, dengan menambahkan pada bagian akhir:

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

masukkan deskripsi gambar di sini


6

Jika Anda ingin label persentase tetapi Ns aktual pada sumbu y, coba ini:

    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

Berikut adalah solusi untuk data faceted. (Jawaban yang diterima oleh @Andrew tidak berfungsi dalam kasus ini.) Idenya adalah untuk menghitung nilai persentase menggunakan dplyr dan kemudian menggunakan geom_col untuk membuat plot.

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

Ini plotnya:

masukkan deskripsi gambar di sini


4

Perhatikan bahwa jika variabel Anda kontinu, Anda harus menggunakan geom_histogram (), karena fungsi akan mengelompokkan variabel dengan "bins".

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..))) 
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.