ggplot2添加动态箭头注释,指向特定数据点,并保持与整个图比例成比例。

3
我希望创建一个模板,可以让我创建一条股票价格折线图,并能够添加指向特定日期的箭头。 ggplot2的注释功能不允许随着图表的比例调整大小。是否有任何解决方法?
例如,在此仅包含6个日期的情节中,箭头与图表的大小相匹配:
prices<-c(3,5,28,17,62,10)
prices2<-prices-1
prices3<-prices-11
dates<-seq.Date(from=as.Date("2018-1-1"),to=as.Date("2018-1-6"),"days")

ggplot()+
geom_line(aes(dates,prices))+
annotate(
"segment",
x=dates,
xend=dates,
y=prices3,
yend=prices2,
color="blue",
arrow=arrow(length=unit(0.5,"cm")
            ))

插入图像描述

然而,当我将周期增加到15天时,箭头比例不成比例,看起来像这样:

插入图像描述


1
我的第一个想法是尝试使用相对单位,如“npc”,而不是在指定箭头长度时使用“cm”。 - joran
你是如何生成 prices3 和 prices2 的呢? - august
它们只是我编造的一组随机数列。prices<-c(3,5,28,17,62,10) - TG_01
NPC看起来更好了,但仍然不能生成比例大小的箭头。这是DF的代码:prices<-c(3,5,28,17,62,10) prices2<-prices-1 prices3<-prices-11 dates<-seq.Date(from=as.Date("2018-1-1"),to=as.Date("2018-1-6"),"days") - TG_01
是的,箭头大小是一个独立的事物(因为它不是由长度参数直接控制的)。我在这里看到过几个人纠结于如何正确调整它们的大小。如果你搜索一下,可能会找到一些有用的东西,但我的印象是这很麻烦。 - joran
进一步的复杂性是当我将折线图转换为对数刻度时,会进一步影响箭头的位置。 - TG_01
1个回答

2
我不确定您所说的“proportional”具体是什么意思,它是否与第一个图形具有相同的比例长度?如果是这样的话,由于箭头的长度受到 prices2prices3 的控制,您可以计算出它们在第一个图形上所占比例的空间,然后再计算第二个图形。结合 npc 来绘制箭头,应该能够大致得到您想要的效果。由于 x 轴的问题,箭头本身并不完美,但我认为它比之前更接近了。

因此,使用您的数据:

# original data
prices<-c(3,5,28,17,62,10)
dates<-seq.Date(from=as.Date("2018-1-1"),to=as.Date("2018-1-6"),"days")

# original plot (with 0.05 npc)
ggplot()+
    geom_line(aes(dates,prices))+
    annotate(
        "segment",
        x=dates,
        xend=dates,
        y=prices-11,
        yend=prices-1,
        color="blue",
        arrow=arrow(length=unit(0.05,"npc")
        ))

enter image description here

# new data
prices2<-c(prices,c(20,250,30,60,40))
dates2 <- seq.Date(from=as.Date("2018-1-1"),to=as.Date("2018-1-11"),"days")

# compute length of arrow
p1 <- abs(min(prices)-11)+max(prices)
fs1<-function(x) { (abs(min(prices2)-x)+max(prices2))*11/p1-x }
y1<-uniroot(fs2,lower=0,upper=100)$root

p2 <- abs(min(prices)-1)+max(prices)
fs2<-function(x) { (abs(min(prices2)-x)+max(prices2))*1/p2-x }
y2<-uniroot(fs1,lower=0,upper=100)$root

# new plot
ggplot()+
geom_line(aes(dates2,prices2))+
annotate(
    "segment",
    x=dates2,
    xend=dates2,
    y=prices2-y1,
    yend=prices2-y2,
    color="blue",
    arrow=arrow(length=unit(0.05,"npc")
    ))

enter image description here


谢谢,我想我想出了一个类似的想法: prices2<-prices-(max(prices)/100)*2 prices3<-prices-(max(prices)/100)*8 它将箭头设置为最小值和最大值,并将长度设置为一些预定图形,该图形从0-100。 但是如果您正在对数基础上绘图,您会怎么做? - TG_01
在绘图之前转换数据,而不是使用scale_y_log10(),然后应用相同的原则。 - august
ggplot()+ geom_line(aes(dates,log(prices)))+ annotate( "segment", x=dates, xend=dates, y=log(prices)-max(log(prices))/100*8, yend=log(prices)-max(log(prices))/100*2, color="blue", arrow=arrow(length=unit(0.03,"npc") )) - august
谢谢,那个方法可行,但是 Y 轴的标签不正确。我需要的是注释相对于图表大小自动调整大小,而不是根据数据进行调整。另一个解决方案是使用对数基础的公式来调整大小。 - TG_01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接