Cara menampilkan hanya nilai integer pada sumbu menggunakan ggplot2

88

Saya memiliki plot berikut:

library(reshape)
library(ggplot2)
library(gridExtra)
require(ggplot2)



data2<-structure(list(IR = structure(c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L
), .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"
), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), .Label = c("Real queens", "Simulated individuals"
), class = "factor"), value = c(15L, 11L, 29L, 42L, 0L, 5L, 21L, 
22L), Legend = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Real queens", 
"Simulated individuals"), class = "factor")), .Names = c("IR", 
"variable", "value", "Legend"), row.names = c(NA, -8L), class = "data.frame")
p <- ggplot(data2, aes(x =factor(IR), y = value, fill = Legend, width=.15))


data3<-structure(list(IR = structure(c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L
), .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"
), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), .Label = c("Real queens", "Simulated individuals"
), class = "factor"), value = c(2L, 2L, 6L, 10L, 0L, 1L, 4L, 
4L), Legend = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Real queens", 
"Simulated individuals"), class = "factor")), .Names = c("IR", 
"variable", "value", "Legend"), row.names = c(NA, -8L), class = "data.frame")
q<- ggplot(data3, aes(x =factor(IR), y = value, fill = Legend, width=.15))


##the plot##
q + geom_bar(position='dodge', colour='black') + ylab('Frequency') + xlab('IR')+scale_fill_grey() +theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="Black"))+ opts(title='', panel.grid.major = theme_blank(),panel.grid.minor = theme_blank(),panel.border = theme_blank(),panel.background = theme_blank(), axis.ticks.x = theme_blank())

Saya ingin sumbu y hanya menampilkan bilangan bulat. Apakah ini dicapai melalui pembulatan atau melalui metode yang lebih elegan tidak terlalu penting bagi saya.

Atticus 29
sumber
2
Pernahkah Anda melihat salah satu fungsi skala sama sekali? scale_y_continuousmungkin?
joran
Saya membaca beberapa jawaban untuk pertanyaan serupa dan mendapat kesan bahwa scale_y_continuous dikonversi dari format numerik lain (misalnya, notasi ilmiah), tetapi tidak mengakomodasi konversi bilangan real ke integer yang saya cari. Saya mungkin salah ...
Atticus29

Jawaban:

42

Dengan scale_y_continuous()argumen dan breaks=Anda dapat mengatur titik putus untuk sumbu y menjadi bilangan bulat yang ingin Anda tampilkan.

ggplot(data2, aes(x =factor(IR), y = value, fill = Legend, width=.15)) +
    geom_bar(position='dodge', colour='black')+
    scale_y_continuous(breaks=c(1,3,7,10))
Didzis Elferts
sumber
45
Solusi ini hanya bagus untuk situasi di mana Anda tahu nilai mana yang ada di sumbu. Bukan solusi umum yang bagus.
swolf
4
Catatan untuk anak cucu: geom_bartidak lagi berfungsi dengan estetika y (ganti dengan geom_col). Dan, meskipun bukan solusi umum, dalam contoh ini, memanggil pretty dengan n tertentu dapat memperbaiki masalah asli (dan lebih fleksibel daripada jeda hard-coding): q + geom_col(position='dodge', colour='black') + xlab('IR')+scale_fill_grey() + theme_bw() + scale_y_continuous('Frequency', breaks=function(x) pretty(x, n=6))
helmingstay
73

Jika Anda memiliki scalespaketnya, Anda dapat menggunakan pretty_breaks()tanpa harus menentukan jeda secara manual.

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks= pretty_breaks())
Sealander
sumber
17
Ini tampaknya melakukan hampir apa yang dilakukan metode default dan saya masih memiliki titik desimal di jeda.
kory
Dari mana pretty_breaks()asalnya
Marian
16
pretty_breaks()cantik, tetapi tidak selalu bilangan bulat. Jelas ada keindahan dalam desimal ...
PatrickT
51

Ini yang saya gunakan:

ggplot(data3, aes(x = factor(IR), y = value, fill = Legend, width = .15)) +
  geom_col(position = 'dodge', colour = 'black') + 
  scale_y_continuous(breaks = function(x) unique(floor(pretty(seq(0, (max(x) + 1) * 1.1)))))
Daniel Gardiner
sumber
Ini adalah jawaban pertama yang berhasil, tetapi seorang penjelajah akan lebih dari diterima.
DomQ
18

Anda dapat menggunakan labeller khusus. Misalnya, fungsi ini menjamin untuk hanya menghasilkan pemutusan bilangan bulat:

int_breaks <- function(x, n = 5) {
  l <- pretty(x, n)
  l[abs(l %% 1) < .Machine$double.eps ^ 0.5] 
}

Digunakan sebagai

+ scale_y_continuous(breaks = int_breaks)

Ia bekerja dengan mengambil jeda default, dan hanya mempertahankan yang merupakan bilangan bulat. Jika itu menunjukkan jeda terlalu sedikit untuk data Anda, tingkatkan n, misalnya:

+ scale_y_continuous(breaks = function(x) int_breaks(x, n = 10))
Axeman
sumber
Yang ini menyebabkan Anda kehilangan integer 1 jika Anda memiliki data hanya dari 0 - 1,25 atau apa yang Anda miliki. Saya hanya melihat 0 pada sumbu x.
kory
1
Saya suka ini demi kesederhanaan. Perhatikan bahwa ndapat menggunakan beberapa penyesuaian tergantung pada rentang nilai Anda. tampaknya menentukan berapa banyak jeda yang akan ada (secara kasar).
Marian
15

Solusi ini tidak berhasil untuk saya dan tidak menjelaskan solusinya.

The breaksargumen ke scale_*_continuousfungsi dapat digunakan dengan fungsi kustom yang mengambil batas sebagai masukan dan kembali istirahat sebagai output. Secara default, batas sumbu akan diperluas sebesar 5% di setiap sisi untuk data berkelanjutan (relatif terhadap rentang data). Batas sumbu kemungkinan besar bukan nilai integer karena perluasan ini.

Solusi yang saya cari adalah dengan membulatkan batas bawah ke bilangan bulat terdekat, membulatkan batas atas ke bilangan bulat terdekat, dan kemudian memutus nilai bilangan bulat di antara titik-titik akhir ini. Oleh karena itu, saya menggunakan fungsi jeda:

brk <- function(x) seq(ceiling(x[1]), floor(x[2]), by = 1)

Cuplikan kode yang diperlukan adalah:

scale_y_continuous(breaks = function(x) seq(ceiling(x[1]), floor(x[2]), by = 1))

Contoh yang dapat direproduksi dari pertanyaan asli adalah:

data3 <-
  structure(
    list(
      IR = structure(
        c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L),
        .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"),
        class = "factor"
      ),
      variable = structure(
        c(1L, 1L, 1L, 1L,
          2L, 2L, 2L, 2L),
        .Label = c("Real queens", "Simulated individuals"),
        class = "factor"
      ),
      value = c(2L, 2L, 6L, 10L, 0L, 1L, 4L,
                4L),
      Legend = structure(
        c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L),
        .Label = c("Real queens",
                   "Simulated individuals"),
        class = "factor"
      )
    ),
    row.names = c(NA,-8L),
    class = "data.frame"
  )

ggplot(data3, aes(
  x = factor(IR),
  y = value,
  fill = Legend,
  width = .15
)) +
  geom_col(position = 'dodge', colour = 'black') + ylab('Frequency') + xlab('IR') +
  scale_fill_grey() +
  scale_y_continuous(
    breaks = function(x) seq(ceiling(x[1]), floor(x[2]), by = 1),
    expand = expand_scale(mult = c(0, 0.05))
    ) +
  theme(axis.text.x=element_text(colour="black", angle = 45, hjust = 1), 
        axis.text.y=element_text(colour="Black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank(), 
        axis.ticks.x = element_blank())
Nat
sumber
2
Jawaban terbaik di sini
Martin
Saya setuju dengan Martin - Terima kasih telah berupaya memberikan contoh yang berfungsi sepenuhnya. Saya perhatikan bahwa jawaban Daniel Gardiner menggunakan fungsi jeda yang lebih baik, yang tidak akan menyebabkan kekacauan saat kisaran sumbu dalam ratusan atau lebih. Selain itu, terkait selera, saya merasa bahwa mendefinisikan dan menggunakan breaks_integersfungsi terpisah bisa lebih membantu bagi pemula. Terbaik,
DomQ
5

Semua jawaban yang ada tampaknya memerlukan fungsi kustom atau gagal dalam beberapa kasus.

Baris ini membuat pemisah bilangan bulat:

bad_scale_plot +
  scale_y_continuous(breaks = scales::breaks_extended(Q = c(1, 5, 2, 4, 3)))

Untuk info lebih lanjut, lihat dokumentasi ?labeling::extended(yang dipanggil oleh fungsi scales::breaks_extended).

Pada dasarnya, argumennya Qadalah sekumpulan angka bagus yang coba digunakan algoritme untuk pemutusan skala. Plot asli menghasilkan istirahat non-integer (0, 2,5, 5, dan 7,5) karena nilai default untuk Qmencakup 2,5: Q = c(1,5,2,2.5,4,3).

EDIT: seperti yang ditunjukkan dalam komentar, pemutusan non-integer dapat terjadi ketika sumbu y memiliki rentang kecil. Secara default, breaks_extended()mencoba untuk melakukan n = 5break, yang tidak mungkin dilakukan jika kisarannya terlalu kecil. Pengujian cepat menunjukkan bahwa rentang yang lebih lebar dari 0 <y <2.5 memberikan pemutusan bilangan bulat ( njuga dapat diturunkan secara manual).

Nick
sumber
3

Google membawa saya ke pertanyaan ini. Saya mencoba menggunakan bilangan real dalam skala ay. Angka skala y dalam Jutaan.

The timbangan paket commametode memperkenalkan koma untuk jumlah besar saya. Posting di R-Blogger ini menjelaskan pendekatan sederhana menggunakan commametode:

library(scales)

big_numbers <- data.frame(x = 1:5, y = c(1000000:1000004))

big_numbers_plot <- ggplot(big_numbers, aes(x = x, y = y))+
geom_point()

big_numbers_plot + scale_y_continuous(labels = comma)

Nikmati R :)

Tony Cronin
sumber
1
Solusi lain di sini tidak benar-benar berhasil untuk saya, atau tampak sangat rumit. Yang ini berhasil dan mudah dilakukan.
Brian Doherty
terima kasih @BrianDoherty, kesederhanaan adalah kunci untuk banyak hal ...
Tony Cronin
2

Saya menemukan solusi ini dari Joshua Cook dan bekerja dengan cukup baik.

integer_breaks <- function(n = 5, ...) {
fxn <- function(x) {
breaks <- floor(pretty(x, n, ...))
names(breaks) <- attr(breaks, "labels")
breaks
}
return(fxn)
}

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks = integer_breaks())

Sumbernya adalah: https://joshuacook.netlify.app/post/integer-values-ggplot-axis/

Bruno Vidigal
sumber
Fungsi ini harus menjadi jawaban yang benar. Bekerja lebih mudah dari apapun!
zdebruine
1

Jawaban ini dibangun atas jawaban @ Axeman untuk menjawab komentar oleh kory bahwa jika data hanya berjalan dari 0 ke 1, tidak ada jeda yang ditampilkan di 1. Ini tampaknya karena ketidakakuratan prettydengan keluaran yang tampaknya 1 tidak identik dengan 1 (lihat contoh di akhir).

Karena itu jika Anda menggunakan

int_breaks_rounded <- function(x, n = 5)  pretty(x, n)[round(pretty(x, n),1) %% 1 == 0]

dengan

+ scale_y_continuous(breaks = int_breaks_rounded)

baik 0 dan 1 ditampilkan sebagai jeda.

Contoh untuk menggambarkan perbedaan dari Axeman

testdata <- data.frame(x = 1:5, y = c(0,1,0,1,1))

p1 <- ggplot(testdata, aes(x = x, y = y))+
  geom_point()


p1 + scale_y_continuous(breaks = int_breaks)
p1 + scale_y_continuous(breaks =  int_breaks_rounded)

Keduanya akan bekerja dengan data yang diberikan di pertanyaan awal.

Ilustrasi mengapa pembulatan diperlukan

pretty(c(0,1.05),5)
#> [1] 0.0 0.2 0.4 0.6 0.8 1.0 1.2
identical(pretty(c(0,1.05),5)[6],1)
#> [1] FALSE
Sarah
sumber