Arrows Label Direction in ggplot2

2019-05-29 10:50发布

I produced biplot with this R code:

set.seed(12345)
require(ggplot2)
AData <- data.frame(Glabel=LETTERS[1:7], A=rnorm(7, mean = 0, sd = 1), B=rnorm(7, mean = 0, sd = 1))
TData <- data.frame(Tlabel=LETTERS[11:20], A=rnorm(10, mean = 0, sd = 1), B=rnorm(10, mean = 0, sd = 1))
i <- 2
j <- 3
p <- ggplot(data=AData, aes(AData[, i], AData[, j])) + geom_point() + theme_bw()
p <- p + geom_text(aes(data=AData, label=Glabel), size=3, vjust=1.25, colour="black")
p <- p + geom_segment(data = TData, aes(xend = TData[ ,i], yend=TData[ ,j]),
              x=0, y=0, colour="black",
              arrow=arrow(angle=25, length=unit(0.25, "cm")))
p <- p + geom_text(data=TData, aes(x=TData[ ,i], y=TData[ ,j], label=Tlabel), size=3, vjust=1.35, colour="black")

Output enter image description here

Everything is fine except the arrows labels. I'd like to have the labels at the end of the arrows and in the same direction as arrows. Any idea and/or solution. Thanks in advance.

标签: r ggplot2
3条回答
一纸荒年 Trace。
2楼-- · 2019-05-29 11:16

A better solution with label direction as arrows:

set.seed(12345)
require(ggplot2)
AData <- data.frame(Glabel=LETTERS[1:7], A=rnorm(7, mean = 0, sd = 1), B=rnorm(7, mean = 0, sd = 1))
TData <- data.frame(Tlabel=LETTERS[11:20], A=rnorm(10, mean = 0, sd = 1), B=rnorm(10, mean = 0, sd = 1))
i <- 2
j <- 3
p <- ggplot(data=AData, aes(AData[, i], AData[, j])) + geom_point() + theme_bw()
p <- p + geom_text(aes(data=AData, label=Glabel), size=3, vjust=1.25, colour="black")

p <- p + geom_segment(data = TData, aes(xend = TData[ ,i], yend=TData[ ,j]),
              x=0, y=0, colour="black",
              arrow=arrow(angle=25, length=unit(0.25, "cm")))
p <- p + geom_text(
        data=TData
      , aes(x=TData[ ,i], y=TData[ ,j], label=Tlabel
            , angle = (180/pi) * atan(TData[ ,j]/TData[ ,i])
            , hjust = (1 - 2 * sign(TData[ ,i])) / 2)
      , size=3
      , colour="black")

print(p)

enter image description here

查看更多
家丑人穷心不美
3楼-- · 2019-05-29 11:22

Two possibilities:

p <- p + geom_text(data=TData, aes(x=1.2*TData[ ,i], 
                                   y=1.2*TData[ ,j], 
                  label=Tlabel), size=3, vjust=0, colour="black")
p
#-----------------------------------
p <- p + geom_text(data=TData, aes(x=TData[ ,i] +.1*sign(TData[ ,i]), 
                                   y=TData[ ,j]+.1*sign(TData[ ,j]), 
                  label=Tlabel), size=3, vjust=0, colour="black")
p

First one leaves labels away from the arrows a distance that varies with the "strengths" while the second one a fixed distance on the graphics plotting scale (probably the preferred solution and the one illustrated below).

Second version as image

And finally a fully "trigonometricized "version that will get the labels exactly in the same vector as the arrows. (The sameness of the sign(.) argument is a result of the conventions for arctangent values. Ya do what ya gatta do.) :

p <- ggplot(data=AData, aes(AData[, i], AData[, j])) + geom_point() + theme_bw()
p <- p + geom_text(aes(data=AData, label=Glabel), size=3, vjust=1.25, colour="black")
p <- p + geom_segment(data = TData, aes(xend = TData[ ,i], yend=TData[ ,j]),
              x=0, y=0, colour="black",
              arrow=arrow(angle=25, length=unit(0.25, "cm")))
p <- p + geom_text(data=TData, 
            aes(x=TData[ ,i] +.1*cos(atan(TData[ ,j]/TData[ ,i]))*sign(TData[ ,i]), 
                y=TData[ ,j] +.1*sin(atan(TData[ ,j]/TData[ ,i]))*sign(TData[ ,i]), 
            label=Tlabel), size=3, vjust=0, colour="red")
查看更多
成全新的幸福
4楼-- · 2019-05-29 11:25

Any solution will likely require some manual fussing with positioning. But ultimately in your case it will be much easier to plot the labels without the vjust adjustments and then shorten each of the arrows slightly:

#This is the ad-hoc part to tinker with
l <- 1 - (0.05 * sqrt(1/with(TData,A^2 + B^2)))

p <- ggplot(data=AData, aes(AData[, i], AData[, j])) + geom_point() + theme_bw()
p <- p + geom_text(aes(data=AData, label=Glabel), size=3, vjust=1.25, colour="black")

#Scale the segments back slightly
p <- p + geom_segment(data = TData, aes(xend = TData[ ,i] * l, yend=TData[ ,j] * l),
              x=0, y=0, colour="black",
              arrow=arrow(angle=25, length=unit(0.25, "cm")))
p <- p + geom_text(data=TData, aes(x=TData[ ,i], y=TData[ ,j], label=Tlabel), size=3, colour="black")

enter image description here

Note the segment shortening had to happen somewhat proportionally to the length of the segment, since the arrow head lengths themselves are fixed.

查看更多
登录 后发表回答