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 .

wishihadabettername
sumber
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

Andrew
sumber
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.

Ramnath
sumber
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
49

Dengan ggplot2 versi 2.1.0 itu

+ scale_y_continuous(labels = scales::percent)
Fabian Hertwig
sumber
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.

Olivier Ma
sumber
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

Sam Firke
sumber
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)
Steve Powell
sumber
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

ACNB
sumber
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..))) 
Rtist
sumber