使用ggplot2中的线条和箭头连接大点

时间:2016-08-17 19:18:35

标签: r ggplot2

使用ggplot,我想从segment到另一个curve绘制pathpointarrow,其中包括df <- data.frame(x1=10, x2=5, y1=10, y2=5) ggplot(df) + geom_point(aes(x=x1, y=y1)) + geom_point(aes(x=x2, y=y2)) + geom_segment(aes(x=x1, y=y1, xend=x2, yend=y2), arrow = arrow()) 。我的问题是我想将线连接到点的“边缘”而不是中心,这样无论点的大小如何,箭头都是可见的。

例如,以下代码没问题:

ggplot(df) + 
    geom_point(aes(x=x1, y=y1)) + 
    geom_point(aes(x=x2, y=y2), size=20) + 
    geom_segment(aes(x=x1, y=y1, xend=x2, yend=y2), 
        arrow = arrow())

enter image description here

但是,如果我将这些点设得很大,那么箭头就会变得模糊不清:

size

enter image description here

如何调整线条,使箭头的尖端始终与点的边缘相交?

我已经尝试调整行终点的坐标,但SELECT * FROM jsonb_array_elements_text($$["tag1","tag2","xtag1","ytag1"]$$::jsonb) WHERE value LIKE 't%'; value ------- tag1 tag2 (2 rows) 美学与坐标本身的比例不同(讨论here),因此很难知道如何更改以一般化的方式坐标。最相关的类似问题是this,但答案并不能解决我的问题。谢谢!

1 个答案:

答案 0 :(得分:1)

就个人而言,我会寻求手动解决方案:

library(ggplot2)

plot.arr <- function(df, pointsiz=2, pointsiz.scale.factor=100){

    ## calculate weights to adjust for aspect ratio
    norm2 <- function(v) sqrt(sum(v^2))
    w <- c(diff(range(df[ ,c("x1","x2")])), diff(range(df[ ,c("y1","y2")])))
    w <- w/norm2(w)

    ## use "elliptical" norm to account for different scales on x vs. y axes
    norm2w <- function(v) sqrt(sum((v/w)^2))

    ## compute normalized direction vectors, using "elliptical" norm
    direc <- do.call("rbind",lapply(1:nrow(df), function(i) {
        vec <- with(df[i, ], c(dx=x2-x1, dy=y2-y1))
        data.frame(as.list(vec/norm2w(vec)))
    }))

    ## "shift back" endpoints:
    ## translate endpoints towards startpoints by a fixed length;
    ## translation direction is given by the normalized vectors;
    ## translation length is proportional to the overall size of the plot
    ## along both x and y directions
    ## pointsiz.scale.factor can be decreased/increased for larger/smaller pointsizes

    epsil <- direc * diff(range(df)) / pointsiz.scale.factor
    df$xend2 <- df$x2 - epsil$dx
    df$yend2 <- df$y2 - epsil$dy

    g <- ggplot(df) + 
        geom_point(aes(x=x1, y=y1), size=pointsiz) + 
        geom_point(aes(x=x2, y=y2), size=pointsiz) + 
        geom_segment(aes(x=x1, y=y1, xend=xend2, yend=yend2), 
                     arrow = arrow())        
    print(g)
}
set.seed(124)
##n.arr <- 1
n.arr <- 3

df <- data.frame(x1=10+rnorm(n.arr,10,400),
                 x2=5 +rnorm(n.arr,1),
                 y1=10+rnorm(n.arr,0,5),
                 y2=5 +rnorm(n.arr,2))
plot.arr(df)

df <- data.frame(x1=10+rnorm(n.arr,1000,4000),
                 x2=5 +rnorm(n.arr,1),
                 y1=10+rnorm(n.arr,0,5),
                 y2=5 +rnorm(n.arr,2))
plot.arr(df)


df <- data.frame(x1=10+rnorm(n.arr,3,4),
                 x2=5 +rnorm(n.arr,1),
                 y1=10+rnorm(n.arr,0,5),
                 y2=5 +rnorm(n.arr,2))
plot.arr(df, pointsiz=4, pointsiz.scale.factor=50)

关于你在下面评论中的(优秀)问题:理想情况下,要正确地解决这个问题,可以执行嵌入在&#34;本地ggplot&#34;中的计算。设置,而不是明确的&#34;手册&#34;以上程序。这可能是可能的,但它需要更深层次的Paul-Murrell知识,我绝对不具备这些知识。具体来说:在上面的第三个图之后我尝试了

ggsave("test1.pdf", width=6, height=6)
ggsave("test2.pdf", width=16, height=6)

使用较大的宽度会产生拉伸箭头点和端点之间距离的副作用,因为三个箭头或多或​​少水平对齐;在目视检查pdf文件后,除了手动调整pointsiz.scale.factor之外,我认为没有其他选择。唉,这绝对不是&#34;原生ggplot&#34;:它是蛮力的,后验的试错;然而,如果pdf的纵横比是预先确定的 - 新的纵横比需要新的试错法估计,它可以显示在线性个人时间内收敛。当使用更大的点数时,类似的评论仍然存在:为了找到箭头点和点边缘之间视觉上令人愉悦的距离,我认为除了反复试验之外别无选择。这是手工方法的局限......