gunakan unit npc di annotate ()

Sep 04 2020

Saya memiliki objek ggplot. Saya ingin menambahkan beberapa teks dengan annotate(), dan saya ingin menentukan koordinat teks dalam unit npc. Apakah ini mungkin?

Contoh minimal ini menunjukkan bagaimana teks biasanya diposisikan dengan annotate():

library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + annotate("text", x = 30, y = 4.5, label = "hello")

Saya ingin mencapai efek yang sama, tetapi alih-alih menentukan xdan ydalam koordinat asli, saya ingin menentukannya dengan koordinat npc. Untuk tujuan contoh ini, saya tidak khawatir tentang menerjemahkan x = 30dan y = 4.5menjadi unit npc. Saya hanya ingin tahu apakah unit npc dapat digunakan annotate()sama sekali.

Ada dua strategi terkait, tetapi tidak sepenuhnya memuaskan:

  1. Seseorang dapat menggunakan unit npc dengan menspesifikasikannya menjadi, katakanlah grid::textGrob(),. Dan seseorang kemudian dapat menempatkan grob dengan annotation_custom(), seperti dalam jawaban ini oleh @baptiste . Tetapi solusi ini sedikit lebih rumit daripada yang saya inginkan.

  2. Paket "ggpmisc" termasuk geom_text_npc(). Tapi itu belum bekerja dengan annotate(). Artinya, annotate("text_npc", ...)sepertinya tidak berhasil. [Sunting: sekarang bekerja. Lihat pesan Pedro Aphalo di bawah ini.]

Ada juga banyak postingan terkait. Secara khusus, Greg Snow telah menyarankan penggunaan kisi untuk membuat area pandang dengan dimensi pdan kemudian menjelaskan area pandang tersebut. Dan @teunbrand telah menyarankan metode yang memerlukan konversi pke objek "gtable" (dengan ggplotGrob()) dan kemudian menggambar objek "gtable" itu. Salah satu dari strategi ini mungkin dapat disesuaikan dengan tujuan saya. Tetapi apakah ada cara yang lebih mudah untuk menggunakan koordinat npc annotate()?

Jawaban

6 AllanCameron Sep 04 2020 at 20:31

Secara pribadi, saya akan menggunakan metode Baptiste tetapi dibungkus dengan fungsi khusus agar tidak terlalu kikuk:

annotate_npc <- function(label, x, y, ...)
{
  ggplot2::annotation_custom(grid::textGrob(
    x = unit(x, "npc"), y = unit(y, "npc"), label = label, ...))
}

Yang memungkinkan Anda melakukan:

p + annotate_npc("hello", 0.5, 0.5)

Perhatikan bahwa ini akan selalu menggambar anotasi Anda di ruang npc viewport setiap panel di plot, (yaitu relatif terhadap area berbayang abu-abu daripada seluruh jendela plot) yang membuatnya berguna untuk facet. Jika Anda ingin menggambar anotasi Anda dalam koordinat npc absolut (sehingga Anda memiliki opsi untuk membuat plot di luar area pandang panel), dua opsi Anda adalah:

  1. Matikan kliping dengan coord_cartesian(clip = "off")dan balikkan koordinat x, y dari koordinat npc yang diberikan sebelum menggunakan annotate. Ini rumit tapi mungkin
  2. Gambarlah langsung saat menggunakan grid. Ini jauh lebih mudah, tetapi memiliki sisi negatifnya yaitu anotasi harus digambar di atas plot daripada menjadi bagian dari plot itu sendiri. Anda bisa melakukannya seperti ini:
annotate_npc_abs <- function(label, x, y, ...) 
{
  grid::grid.draw(grid::textGrob(
    label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}

Dan sintaksnya akan sedikit berbeda:

p 
annotate_npc_abs("hello", 0.05, 0.75)

1 PedroAphalo Sep 11 2020 at 00:20

Mulai 'ggpmisc' (> = 0.3.6) kode berikut berfungsi seperti yang diharapkan (dalam CRAN mulai 2020-09-10).

library(ggpmisc)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
# default justification is "inward"
p + annotate("text_npc", npcx = 0.8, npcy = 0.75, label = "hello")
# same justification as default for "geom_text()"
p + annotate("text_npc", npcx = 0.8, npcy = 0.75, label = "hello",
             hjust = "center", vjust = "middle")