Apakah ada cara untuk memanipulasi jeda dan label skala ggplot?

ggplot umumnya berfungsi dengan baik dalam menciptakan jeda dan label yang masuk akal dalam skala.

Namun, saya menemukan bahwa dalam plot dengan banyak segi dan mungkin pernyataan formatter=, labelnya cenderung menjadi terlalu "padat" dan dicetak berlebihan, misalnya pada gambar ini:

df <- data.frame(
        fac=rep(LETTERS[1:10], 100),
        x=rnorm(1000)
)

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(formatter="percent")

masukkan deskripsi gambar di sini

Saya tahu bahwa saya dapat menentukan jeda dan label skala secara eksplisit, dengan memberikan argumen breaks= dan scale= ke scale_x_continuous.

Namun, saya memproses data survei dengan banyak pertanyaan dan selusin crossbreak, jadi perlu mencari cara untuk melakukannya secara otomatis.

Apakah ada cara untuk memberitahu ggplot untuk menghitung jeda dan label secara otomatis, tetapi hanya memiliki lebih sedikit, katakanlah pada titik minimum, maksimum, dan nol?

EDIT: Idealnya, saya tidak ingin menentukan titik minimum dan maksimum, namun memanfaatkan pelatihan skala ggplot bawaan, dan menggunakan batas skala terhitung default.


person Andrie    schedule 21.03.2011    source sumber


Jawaban (2)


Anda dapat meneruskan argumen seperti min() dan max() dalam panggilan Anda ke ggplot untuk menentukan jeda secara dinamis. Sepertinya Anda akan menerapkan ini di berbagai macam data sehingga Anda mungkin ingin mempertimbangkan untuk menggeneralisasikannya ke dalam suatu fungsi dan mengacaukan formatnya, tetapi pendekatan ini akan berhasil:

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(breaks = c(min(df$x), 0, max(df$x))
    , labels = c(paste( 100 * round(min(df$x),2), "%", sep = ""), paste(0, "%", sep = ""), paste( 100 * round(max(df$x),2), "%", sep = ""))
    )

atau putar teks sumbu x dengan opts(axis.text.x = theme_text(angle = 90, hjust = 0)) untuk menghasilkan sesuatu seperti:

masukkan deskripsi gambar di sini

Perbarui

Dalam versi terbaru ggplot2 argumen breaks dan labels untuk scale_x_continuous menerima fungsi, sehingga seseorang dapat melakukan hal seperti berikut:

myBreaks <- function(x){
    breaks <- c(min(x),median(x),max(x))
    names(breaks) <- attr(breaks,"labels")
    breaks
}

ggplot(df, aes(x=x)) + 
  geom_bar(binwidth=0.5) + 
  facet_grid(~fac) + 
  scale_x_continuous(breaks = myBreaks,labels = percent_format()) + 
  opts(axis.text.x = theme_text(angle = 90, hjust = 1,size = 5))
person Chase    schedule 21.03.2011
comment
@Chase Terima kasih. Ya, saya telah mempertimbangkan untuk melakukan hal ini, tetapi ini tidak ideal. Alasannya, datanya bisa berupa persentase, jumlah responden, skor t-stat, atau apa saja. Menghitung magnitudo terdekat mungkin bisa menjadi sebuah pilihan, tapi sebenarnya yang ingin saya lakukan adalah menggunakan skala yang dilatih ggplot, lalu menyembunyikan label di antara titik akhir. Dengan kata lain, suatu saat saya ingin skala atas menjadi (misalnya) 60%. Saya harap ini masuk akal. - person Andrie; 21.03.2011
comment
@Andrie - mengerti. Jadi yang benar-benar Anda butuhkan di sini adalah fungsi yang menafsirkan tipe data yang ditampilkan pada sumbu x (persentase, jumlah, dll...) dan mengubah skalanya, bukan? Bisakah Anda menggunakan class() pada kolom untuk membantu menginformasikan hal ini? Atau data/metdata lain yang menginformasikan apa sebenarnya yang Anda rencanakan? Seharusnya tidak terlalu sulit untuk menulis fungsi kecil untuk menghasilkan vektor jeda dan label untuk diteruskan ke scale_x_continuous() dengan asumsi Anda memiliki beberapa info untuk menginformasikan apa dan bagaimana memformat. - person Chase; 21.03.2011
comment
@Chase Saya berharap seseorang akan memberikan pendekatan yang lebih umum. Misalnya, saat bekerja dengan segi dan skala bebas, mis. facet_grid(~fac, Scales=free), break point tinggi dan rendah secara umum akan berbeda untuk setiap facet. Jadi yang sebenarnya saya kejar adalah menyembunyikan label tanpa menentukan jeda. - person Andrie; 21.03.2011
comment
@Andrie mungkin Anda dapat memberikan kumpulan data sampel terbaru yang menggambarkan masalah Anda dengan lebih baik? Dari apa yang saya tahu, Anda memiliki setidaknya dua masalah berbeda. 1. Overplotting sumbu skala, 2. menggunakan potongan kode yang sama untuk menyajikan data yang sama dalam pencahayaan yang berbeda. Anda dapat mengatasi overplotting dengan sesuatu seperti ... + opts(axis.text.x = theme_text(angle = 90, hjust = 0)). Jika Anda ingin mengatasi masalah pemformatan, saya pikir Anda harus menulis fungsi Anda sendiri untuk meneruskan parameter ke labels() dan breaks(). - person Chase; 22.03.2011
comment
+1 untuk menyarankan perubahan sudut teks dan ukuran teks. Ini akan membantu kebutuhan presentasi saya yang mendesak. - person Andrie; 22.03.2011
comment
+1,5 untuk diterima. FYI, Hadley Wickham menjawab di forum lain bahwa apa yang ingin saya lakukan tidak mudah untuk dilakukan saat ini, namun dalam waktu dekat rilis seseorang akan memiliki kontrol lebih besar atas jeda dan tanda centang. - person Andrie; 22.03.2011

Paket scales berisi beberapa fungsi breaks_* dan label_* yang mengembalikan fungsi (penutupan) yang digunakan oleh ggplot. Jadi, Anda dapat menulis pembungkus untuk ini yang mengubah hasilnya.

Misalnya:

library(ggplot2)

# Compute the list of breaks using original_func,
# then remove any of these that occur in remove_list
remove_breaks <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    original_result[!(original_result %in% remove_list)]
  }
}

# Compute the list of labels using original_func,
# then remove any of these that occur in remove_list
remove_labels <- function(original_func, remove_list = list()) {
  function(x) {
    original_result <- original_func(x)
    replace(original_result, original_result %in% remove_list, '')
  }
}

# Original plot
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = scales::label_number_auto())

# Remove some breaks from the x-axis, and remove some labels from the y-axis
ggplot(data.frame(x=c(1,2,3,4,5,6,7,8), y = c(1,4,9,16,25,36,49,64))) + geom_line(aes(x, y)) +
  scale_x_continuous(breaks       = remove_breaks(scales::breaks_pretty(9), seq(3,6)),
                     minor_breaks = remove_breaks(scales::breaks_pretty(18), seq(3,6,0.5)),
                     labels       = scales::label_number_auto()) +
  scale_y_continuous(breaks       = scales::breaks_pretty(9),
                     minor_breaks = scales::breaks_pretty(18),
                     labels       = remove_labels(scales::label_number_auto(), seq(20, 30)))

Tentu saja, dengan fungsi remove_breaks dan remove_labels saya yang sederhana, Anda masih harus menentukan nilai mana yang akan dihapus, namun Anda dapat dengan mudah memodifikasinya menjadi sesuatu yang menghilangkan nilai maks dan min, menghapus nilai apa pun dalam rentang tertentu, dll.

person Tim Goodman    schedule 18.03.2020
comment
Tulis jawaban sebelum memperhatikan berapa umur pertanyaannya ????. - person Tim Goodman; 18.03.2020