2017-03-27 1 views
0

J'ai une question qui se développe sur this un. Fondamentalement, je veux ajouter bty = "n" à un graphique ggplot2 dans un bon façon. L'accent sur la propriété ici parce que la solution dans l'autre question presque ce que je veux, sauf pour ce détail: enter image description here Je voudrais si la ligne d'axe continuerait jusqu'à la fin de la tique, pas jusqu'au milieu de celui-ci. Tout d'abord, le code pour le graphique:ggplot avec bty = "n", ou comment ajouter des coordonnées de grille pour tracer les coordonnées

library(ggplot2) 
library(grid) 

graph = ggplot(faithful, aes(x=eruptions, y=waiting)) + 
    geom_point(shape=21) + 
    theme(
    # tick width, a bit exaggerated as example 
    axis.ticks = element_line(size = 5, color = "gray") 
    ) 
graph # graph with no axis lines 

# get axis limits 
gb = ggplot_build(graph) 
xLim = range(gb$layout$panel_ranges[[1]]$x.major_source) 
yLim = range(gb$layout$panel_ranges[[1]]$y.major_source) 

# add lines 
graph + 
    geom_segment(y = -Inf, yend = -Inf, x = xLim[1], xend = xLim[2]) + 
    geom_segment(x = -Inf, xend = -Inf, y = yLim[1], yend = yLim[2]) 

Le problème est: Je dessine sur l'axe x de 50 jusqu'à 90. Mais, les coches sont centrées sur 50 et 90, par conséquent, ils étendent de la moitié de size = 5 sur de chaque côté. ?element_line me dit que la taille de la ligne/bordure est par défaut en mm. Ainsi, je veux tracer la ligne de 50 - 5 mm/2 jusqu'à 90 + 5 mm/2. J'ai essayé (de nombreuses variantes de) ce qui suit:

xLim = range(gb$layout$panel_ranges[[1]]$x.major_source) 
yLim = range(gb$layout$panel_ranges[[1]]$y.major_source) 

uType = "npc" 
uType2 = "mm" 

# attempt conversion of units 
xLim[1] = xLim[1] - convertWidth(unit(2.5, units = uType2), 
         unitTo = uType, valueOnly = TRUE) 
xLim[2] = xLim[2] + convertWidth(unit(2.5, units = uType2), 
         unitTo = uType, valueOnly = TRUE) 

yLim[1] = yLim[1] - convertHeight(unit(2.5, units = uType2), 
          unitTo = uType, valueOnly = TRUE) 
yLim[2] = yLim[2] - convertHeight(unit(2.5, units = uType2), 
          unitTo = uType, valueOnly = TRUE) 

# redraw graph  
cairo_pdf("Rplot.pdf") 
graph + 
    geom_segment(y = -Inf, yend = -Inf, x = xLim[1], xend = xLim[2]) + 
    geom_segment(x = -Inf, xend = -Inf, y = yLim[1], yend = yLim[2]) 
dev.off() 

Mais pas de chance que ce soit. Des idées?

Répondre

1

Je crois que vous devriez écrire une méthode drawDetails ou similaire pour faire le calcul d'unité au moment du dessin pour que cela fonctionne.

Alternativement (et peut-être plus facile), vous pouvez écrire un tick personnalisé qui s'étend pour couvrir la ligne d'axe.

enter image description here

(Notez que les deux axes ont des largeurs de ligne en raison de leur ordre z IIRC, je pensais que ce bug a été corrigé).

library(ggplot2) 
library(grid) 


element_grob.element_custom_x <- function (element, x = 0:1, y = 0:1, colour = NULL, size = NULL, 
              linetype = NULL, lineend = "butt", default.units = "npc", id.lengths = NULL, 
              ...) 
{ 
    gp <- gpar(lwd = ggplot2:::len0_null(size * .pt), col = colour, lty = linetype, 
      lineend = lineend) 
    element_gp <- gpar(lwd = ggplot2:::len0_null(element$size * .pt), col = element$colour, 
        lty = element$linetype, lineend = element$lineend) 
    arrow <- if (is.logical(element$arrow) && !element$arrow) { 
    NULL 
    } 
    else { 
    element$arrow 
    } 
    g1 <- polylineGrob(x, y, default.units = default.units, 
        gp = utils::modifyList(element_gp, gp), 
        id.lengths = id.lengths, arrow = arrow, ...) 

    vertical <- length(unique(element$x)) == 1 && length(unique(element$y)) >= 1 

    g2 <- grid::editGrob(g1, y=y + unit(1,"mm"), gp=utils::modifyList(gp, list(col="green")), name="new") 

    grid::grobTree(g2, g1) 

} 


element_grob.element_custom_y <- function (element, x = 0:1, y = 0:1, colour = NULL, size = NULL, 
              linetype = NULL, lineend = "butt", default.units = "npc", id.lengths = NULL, 
              ...) 
{ 
    gp <- gpar(lwd = ggplot2:::len0_null(size * .pt), col = colour, lty = linetype, 
      lineend = lineend) 
    element_gp <- gpar(lwd = ggplot2:::len0_null(element$size * .pt), col = element$colour, 
        lty = element$linetype, lineend = element$lineend) 
    arrow <- if (is.logical(element$arrow) && !element$arrow) { 
    NULL 
    } 
    else { 
    element$arrow 
    } 
    g1 <- polylineGrob(x, y, default.units = default.units, 
        gp = utils::modifyList(element_gp, gp), 
        id.lengths = id.lengths, arrow = arrow, ...) 

    g2 <- grid::editGrob(g1, x=x + unit(1,"mm"), gp=utils::modifyList(gp, list(col="green")), name="new") 

    grid::grobTree(g2, g1) 

} 


## silly wrapper to fool ggplot2 
x_custom <- function(...){ 
    structure(
    list(...), # this ... information is not used, btw 
    class = c("element_custom_x","element_blank", "element") # inheritance test workaround 
) 

} 
y_custom <- function(...){ 
    structure(
    list(...), # this ... information is not used, btw 
    class = c("element_custom_y","element_blank", "element") # inheritance test workaround 
) 

} 

graph = ggplot(faithful, aes(x=eruptions, y=waiting)) + 
    geom_point(shape=21) + theme_minimal() + 
    theme(
    axis.ticks.x = x_custom(size = 5, colour = "red") , 
    axis.ticks.y = y_custom(size = 5, colour = "red") , 
    axis.ticks.length = unit(2,"mm") 
) 
graph # graph with no axis lines 
gb <- ggplot_build(graph) 
xLim = range(gb$layout$panel_ranges[[1]]$x.major_source) 
yLim = range(gb$layout$panel_ranges[[1]]$y.major_source) 


graph + 
    geom_segment(y = -Inf, yend = -Inf, x = xLim[1], xend = xLim[2],lwd=2) + 
    geom_segment(x = -Inf, xend = -Inf, y = yLim[1], yend = yLim[2],lwd=2)