Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 使用ggplot2中的直线和箭头连接大型点_R_Ggplot2 - Fatal编程技术网

R 使用ggplot2中的直线和箭头连接大型点

R 使用ggplot2中的直线和箭头连接大型点,r,ggplot2,R,Ggplot2,使用ggplot,我想从一个点到另一个点绘制一个段、曲线或路径,包括一个箭头。我的问题是,我想将线连接到点的“边”,而不是中心,这样无论点的大小,箭头都是可见的 例如,以下代码可以: 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,

使用
ggplot
,我想从一个
到另一个点绘制一个
曲线
路径
,包括一个
箭头
。我的问题是,我想将线连接到点的“边”,而不是中心,这样无论点的大小,箭头都是可见的

例如,以下代码可以:

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())

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


我已经尝试过调整直线终点的坐标,但是
大小
美学与坐标本身的比例不同(讨论),因此很难知道如何以可概括的方式更改坐标。最相关的类似问题是,但答案并不能解决我的问题。谢谢

就个人而言,我会选择手动解决方案:

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)

使用较大的宽度会产生拉伸箭头点和端点之间距离的副作用,因为三个箭头或多或少水平对齐;在对pdf文件进行目视检查后,除了手动调整
pointsiz.scale.factor
之外,我看不到其他选项。唉,这绝对不是“本土阴谋”:这是蛮力,是事后的试错;然而,如果pdf的纵横比事先固定,它可以在线性个人时间内收敛——新的纵横比需要新的试错估计。当使用较大的点尺寸时,类似的评论也适用:为了在箭头点和点边缘之间找到一个视觉上令人满意的距离,我认为除了尝试和错误之外没有其他选择。这就是手动方法的限制…

为什么不用不同的颜色绘制箭头,使其在点上方可见?这当然是一个选项。有很多箭头,标签在点的顶部等等。这可能不是很漂亮,但是…哇,太棒了。我试图用更简单的几何学来做这件事,但它不起作用。如何针对不同的纵横比修改此选项(我想将图形打印为具有不同高度/宽度的pdf)?
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)
ggsave("test1.pdf", width=6, height=6)
ggsave("test2.pdf", width=16, height=6)