2017-12-19 275 views
9

Czy istnieje sposób na zamknięcie grotu strzałki w geom_curve? Ten sam kod działa z geom_segment. Może to błąd?Wypełnij strzałkę na geom_curve ggplot2

library(tidyverse) 

set.seed(123) 

data <- data_frame(x = rnorm(10), y = rnorm(10)) 

# NO ARROWHEAD FILL 

ggplot(data, aes(x, y)) + 
    geom_point() + 
    geom_curve(aes(x = 0, y = 0, xend = 1, yend = 1), 
      color = "black", 
      arrow = arrow(type = "closed")) 

# ARROWHEAD FILL WORKS 

ggplot(data, aes(x, y)) + 
    geom_point() + 
    geom_segment(aes(x = 0, y = 0, xend = 1, yend = 1), 
      color = "black", 
      arrow = arrow(type = "closed")) 
+0

Kiedy/Jeśli zadasz problem, możesz odwołać się do tego PR, który właśnie napisałem, aby przywrócić "wypełnienie" do właściwego miejsca. https://github.com/tidyverse/ggplot2/pull/2375 – hrbrmstr

Odpowiedz

7

Nazwałbym to błędem i należy złożyć problem. Do tej pory:

geom_curve2 <- function(mapping = NULL, data = NULL, 
         stat = "identity", position = "identity", 
         ..., 
         curvature = 0.5, 
         angle = 90, 
         ncp = 5, 
         arrow = NULL, 
         lineend = "butt", 
         na.rm = FALSE, 
         show.legend = NA, 
         inherit.aes = TRUE) { 
    layer(
    data = data, 
    mapping = mapping, 
    stat = stat, 
    geom = GeomCurve2, 
    position = position, 
    show.legend = show.legend, 
    inherit.aes = inherit.aes, 
    params = list(
     arrow = arrow, 
     curvature = curvature, 
     angle = angle, 
     ncp = ncp, 
     lineend = lineend, 
     na.rm = na.rm, 
     ... 
    ) 
) 
} 

GeomCurve2 <- ggproto("GeomCurve2", GeomSegment, 
    draw_panel = function(data, panel_params, coord, curvature = 0.5, angle = 90, 
         ncp = 5, arrow = NULL, lineend = "butt", na.rm = FALSE) { 
    if (!coord$is_linear()) { 
     warning("geom_curve is not implemented for non-linear coordinates", 
     call. = FALSE) 
    } 
    trans <- coord$transform(data, panel_params) 

    curveGrob(
     trans$x, trans$y, trans$xend, trans$yend, 
     default.units = "native", 
     curvature = curvature, angle = angle, ncp = ncp, 
     square = FALSE, squareShape = 1, inflect = FALSE, open = TRUE, 
     gp = gpar(
     col = alpha(trans$colour, trans$alpha), 
     fill = alpha(trans$colour, trans$alpha), 
     lwd = trans$size * .pt, 
     lty = trans$linetype, 
     lineend = lineend), 
     arrow = arrow 
    ) 
    } 
) 

co prowadzi do:

ggplot(data, aes(x, y)) + 
    geom_point() + 
    geom_curve2(aes(x = 0, y = 0, xend = 1, yend = 1), 
      color = "black", 
      arrow = arrow(type = "closed")) 

i

enter image description here

+1

Dang, właśnie miałem wkleić dokładnie to samo rozwiązanie. Pokonałeś mnie minutę. Nawet w moim kodzie nazwałem go 'geom_curve2' i' GeomCurve2'. –

+1

:-) i, mam również PR w https://github.com/tidyverse/ggplot2/pull/2375 – hrbrmstr

+0

Czekaj na moją odpowiedź, piszę teraz. –

5

Aby dodać coś pożytecznego do odpowiedzi @hrbrmstr dało, myślę, że zarówno geom_segment() i geom_curve() są niepotrzebnie ograniczone, ponieważ nie pozwalają na określenie koloru wypełnienia strzałek oddzielnie od konturu strzałki. Tutaj zapewniam geom_curve2(), który pozwala ci to zrobić. Zmienione linie (względem kodu ggplot2) są podświetlone.

# copied from ggplot2 `geom_curve` 
geom_curve2 <- function(mapping = NULL, data = NULL, 
         stat = "identity", position = "identity", 
         ..., 
         curvature = 0.5, 
         angle = 90, 
         ncp = 5, 
         arrow = NULL, 
         lineend = "butt", 
         na.rm = FALSE, 
         show.legend = NA, 
         inherit.aes = TRUE) { 
    layer(
    data = data, 
    mapping = mapping, 
    stat = stat, 
    geom = GeomCurve2, # call `GeomCurve2` instead of `GeomCurve` 
    position = position, 
    show.legend = show.legend, 
    inherit.aes = inherit.aes, 
    params = list(
     arrow = arrow, 
     curvature = curvature, 
     angle = angle, 
     ncp = ncp, 
     lineend = lineend, 
     na.rm = na.rm, 
     ... 
    ) 
) 
} 

# copied from ggplot2 `GeomCurve` 
GeomCurve2 <- ggproto("GeomCurve2", GeomSegment, 
    # the following `default_aes =` statement is missing in ggplot2 `GeomCurve` 
    default_aes = aes(colour = "black", fill = "black", size = 0.5, linetype = 1, alpha = NA), 
    draw_panel = function(data, panel_params, coord, curvature = 0.5, angle = 90, 
         ncp = 5, arrow = NULL, lineend = "butt", na.rm = FALSE) { 
    if (!coord$is_linear()) { 
     warning("geom_curve is not implemented for non-linear coordinates", 
       call. = FALSE) 
    } 
    trans <- coord$transform(data, panel_params) 

    curveGrob(
     trans$x, trans$y, trans$xend, trans$yend, 
     default.units = "native", 
     curvature = curvature, angle = angle, ncp = ncp, 
     square = FALSE, squareShape = 1, inflect = FALSE, open = TRUE, 
     gp = gpar(
     col = alpha(trans$colour, trans$alpha), 
     # the following `fill = ` statement is missing in ggplot2 `GeomCurve` 
     fill = alpha(trans$fill, trans$alpha), 
     lwd = trans$size * .pt, 
     lty = trans$linetype, 
     lineend = lineend), 
     arrow = arrow 
    ) 
    } 
) 

Teraz możemy określić strzałka wypełnić oddzielnie od konturu:

ggplot(data, aes(x, y)) + 
    geom_point() + 
    geom_curve2(aes(x = 0, y = 0, xend = 1, yend = 1), 
       color = "black", fill = "red", 
       arrow = arrow(type = "closed")) 

enter image description here

Jak zrobić równoważne zmiany geom_segment() pozostawiamy jako ćwiczenie dla czytelnika.

+1

Aye. Zauważyłem, że to dziwne i nie ma "wypełnienia". Zmodyfikuję mój PR dla tego i mam na to CC – hrbrmstr

+1

Gosh Mam nadzieję, że makra auto-re-gen, estetyczne dokumenty sekcji na końcu automatyzacji ggplot2 :-) – hrbrmstr

+1

K. Przesłałem je do "geom_segment' as dobrze i cc'd ciebie na PR. – hrbrmstr