अल्फा सौंदर्यवादी सादे आकार के बजाय तीर के कंकाल को दिखाता है - इसे कैसे रोका जाए?


11

मैं सलाखों के अंत में तीर के साथ एक बार प्लॉट बनाने का लक्ष्य बना रहा हूं। मैं परिभाषित के geom_segmentसाथ चला गया arrow। मैं पारदर्शिता पर एक कॉलम को मैप करना चाहता हूं, लेकिन अल्फ़ा एस्थेटिक एरो ऑब्जेक्ट के साथ ठीक काम नहीं करता है। यहाँ कोड स्निपेट है:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>% 
  ggplot() + geom_segment(aes(x = 0, xend = n, y = y, yend = y, alpha = transparency), 
                          colour = 'red', size = 10, arrow = arrow(length = unit(1.5, 'cm'), type = 'closed')) +
  scale_y_continuous(limits = c(5, 35))

यहाँ छवि विवरण दर्ज करें

यह आसानी से देखा जा सकता है कि arrowवस्तु कम मूल्यों के साथ अच्छी तरह से नहीं दिखती है alpha, अपने कंकाल को सादे, पारदर्शी आकार के बजाय दिखाती है। क्या इसे रोकने का कोई तरीका है?


दिलचस्प अवलोकन - मैं केवल कुछ वर्कअराउंड के बारे में सोच सकता हूं जैसे कि छोटी चौड़ाई के साथ एक अलग सेगमेंट खींचना, जैसे कि इस तरह से:tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>% ggplot() + geom_segment(aes(x = 0, xend = n-10, y = y, yend = y, alpha = transparency), colour = 'red', size = 10) + geom_segment(aes(x = n-0.1, xend = n, y = y, yend = y, alpha = transparency), colour = 'red', size = 1, arrow = arrow(length = unit(1.5, 'cm'), type = 'closed')) + scale_y_continuous(limits = c(5, 35))
वोल्फगैंग अर्नोल्ड

यह वास्तव में दिलचस्प है। मुझे लगता है कि यह अतिव्यापी "कंकाल" के लिए सटीक क्षेत्र की गणना के बिना बचने योग्य नहीं है, और प्रत्येक क्षेत्र के लिए प्रोग्रामेटिक रूप से अल्फा सेट करने के लिए (यह एक भयानक हैक होगा)। यदि आप वास्तव में पारदर्शी तीर चाहते हैं, तो एक और दृष्टिकोण 1) खंड और 2) यह एक त्रिभुज के निकट होगा। (यह भी मुझे काफी हैक की तरह लगता है)।
तजेबो

2
आप निश्चित रूप से सही होंगे कि तीर के लिए एक फ्लैट पारदर्शिता होना अच्छा होगा। मेरा मानना ​​है कि यह ggplot के अंत के किसी भी व्यवहार के कारण नहीं है, लेकिन 'ग्रिड' पैकेज तीर (जिस पर ggplot2 निर्भर करता है) को कैसे खींचता है, इससे संबंधित प्रतीत होता है।
त्युनब्रांड

जवाबों:


13

हम एक नया जियोम बना सकते हैं geom_arrowbar, कि हम किसी भी अन्य जियोम की तरह उपयोग कर सकते हैं, इसलिए आपके मामले में यह वांछित प्लॉट को सिर्फ उसी तरह देगा:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>%
  ggplot() +
  geom_arrowbar(aes(x = n, y = y, alpha = transparency), fill = "red") +
  scale_y_continuous(limits = c(5, 35)) +
  scale_x_continuous(limits = c(0, 350))

यहाँ छवि विवरण दर्ज करें

और इसमें 3 पैरामीटर होते हैं column_width, head_widthऔर head_lengthयदि आप चूक को पसंद नहीं करते हैं, तो आप तीर के आकार को बदलने की अनुमति देते हैं। हम भी भरने के रंग और अन्य सौंदर्यशास्त्र निर्दिष्ट कर सकते हैं:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>%
  ggplot() +
  geom_arrowbar(aes(x = n, y = y, alpha = transparency, fill = as.factor(n)),
                column_width = 1.8, head_width = 1.8, colour = "black") +
  scale_y_continuous(limits = c(5, 35)) +
  scale_x_continuous(limits = c(0, 350))

यहाँ छवि विवरण दर्ज करें

एक ही रोड़ा है कि हमें इसे पहले लिखना होगा!

मौजूदा ggplot2 विगनेट में उदाहरणों के बाद , हम अपने को geom_arrowbarउसी तरह से परिभाषित कर सकते हैं जैसे कि अन्य भू-भाग को परिभाषित करते हैं, सिवाय इसके कि हम अपने 3 मापदंडों में पारित होने में सक्षम होना चाहते हैं जो तीर के आकार को नियंत्रित करते हैं। इन्हें paramsपरिणामी layerवस्तु की सूची में जोड़ा जाता है , जिसका उपयोग हमारे तीर परत बनाने के लिए किया जाएगा:

library(tidyverse)

geom_arrowbar <- function(mapping = NULL, data = NULL, stat = "identity",
                          position = "identity", na.rm = FALSE, show.legend = NA,
                          inherit.aes = TRUE, head_width = 1, column_width = 1,
                          head_length = 1, ...) 
{
  layer(geom = GeomArrowBar, mapping = mapping, data = data, stat = stat,
        position = position, show.legend = show.legend, inherit.aes = inherit.aes,
        params = list(na.rm = na.rm, head_width = head_width,
                      column_width = column_width, head_length = head_length, ...))
}

अब "सभी" जो बना हुआ है उसे परिभाषित करना है कि क्या GeomArrowBarहै। यह प्रभावी रूप से एक ggprotoवर्ग परिभाषा है। इसका सबसे महत्वपूर्ण हिस्सा draw_panelसदस्य फ़ंक्शन है, जो हमारे डेटाफ़्रेम की प्रत्येक पंक्ति को लेता है और इसे तीर आकृतियों में परिवर्तित करता है। एक्स और वाई को-ऑर्डिनेट्स के साथ-साथ हमारे विभिन्न आकार मापदंडों के साथ काम करने के लिए कुछ बुनियादी गणित के बाद, तीर का आकार क्या होना चाहिए, यह grid::polygonGrobहमारे डेटा की प्रत्येक पंक्ति के लिए एक उत्पादन करता है और इसे इसमें स्टोर करता है gTree। यह परत के चित्रमय घटक का निर्माण करता है।

GeomArrowBar <- ggproto("GeomArrowBar", Geom,
  required_aes = c("x", "y"),
  default_aes = aes(colour = NA, fill = "grey20", size = 0.5, linetype = 1, alpha = 1),
  extra_params = c("na.rm", "head_width", "column_width", "head_length"),
  draw_key = draw_key_polygon,
  draw_panel = function(data, panel_params, coord, head_width = 1,
                        column_width = 1, head_length = 1) {
    hwidth <- head_width / 5
    wid <- column_width / 10
    len <- head_length / 10
    data2 <- data
    data2$x[1] <- data2$y[1] <- 0
    zero <- coord$transform(data2, panel_params)$x[1]
    coords <- coord$transform(data, panel_params)
    make_arrow_y <- function(y, wid, hwidth) {
      c(y - wid/2, y - wid/2, y - hwidth/2, y, y + hwidth/2, y + wid/2, y + wid/2)
    }
    make_arrow_x <- function(x, len){
      if(x < zero) len <- -len
      return(c(zero, x - len, x - len , x, x - len, x - len, zero))
    }
    my_tree <- grid::gTree()
    for(i in seq(nrow(coords))){
      my_tree <- grid::addGrob(my_tree, grid::polygonGrob(
        make_arrow_x(coords$x[i], len),
        make_arrow_y(coords$y[i], wid, hwidth),
        default.units = "native",
        gp = grid::gpar(
          col = coords$colour[i],
          fill = scales::alpha(coords$fill[i], coords$alpha[i]),
          lwd = coords$size[i] * .pt,
          lty = coords$linetype[i]))) }
    my_tree}
)

यह कार्यान्वयन एकदम सही है। यह कुछ महत्वपूर्ण कार्यक्षमता को याद कर रहा है, जैसे कि समझदार डिफ़ॉल्ट अक्ष सीमाएं और करने की क्षमताcoord_flip , और यह अनैच्छिक परिणाम उत्पन्न करेगा यदि तीर प्रमुख पूरे स्तंभ की तुलना में लंबे होते हैं (हालांकि आप उस स्थिति में इस तरह के भूखंड का उपयोग नहीं करना चाहते हैं) । हालाँकि, यदि आपके पास ऋणात्मक मान है, तो यह समझदारी से बाईं ओर तीर होगा। एक बेहतर कार्यान्वयन खाली तीर प्रमुखों के लिए एक विकल्प भी जोड़ सकता है।

संक्षेप में, इसे (और अन्य) बगों को बाहर निकालने के लिए बहुत सारे ट्वीक्स की आवश्यकता होगी और इसे उत्पादन के लिए तैयार करना होगा, लेकिन इस बीच बहुत अधिक प्रयास के बिना कुछ अच्छे चार्ट का उत्पादन करना काफी अच्छा है।

रिप्रेक्स पैकेज (v0.3.0) द्वारा 2020-03-08 को बनाया गया


4

geom_gene_arrowसे उपयोग कर सकते थेlibrary(gggenes)

data.frame(y=c(10, 20, 30), n=c(300, 100, 200), transparency=c(10, 2, 4)) %>% 
  ggplot() + 
  geom_gene_arrow(aes(xmin = 0, xmax = n, y = y, alpha = transparency), 
                  arrowhead_height = unit(6, "mm"), fill='red') +
  scale_y_continuous(limits = c(5, 35))

यहाँ छवि विवरण दर्ज करें


2
यह वह पहिया होना चाहिए जिसे मैंने अभी पुनर्निर्मित किया है! ;)
एलन कैमरन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.