代码之家  ›  专栏  ›  技术社区  ›  HSJ

如何绘制R中geom_段/ggplot2的定向蜘蛛网?

  •  7
  • HSJ  · 技术社区  · 6 年前

    我正试图画出所谓的蜘蛛网(spider network) 欲望线(desire line) which examples movement of things(person,vehicle,etc.)between specific zones by direction.

    这是我正在使用的数据帧:

    df<-data.frame(o=c(1,2,4,4,4,4,6,6,6,7,7,7,9,9,9,9,9,10,10,11,12,12,32,86108128157157157157157157157157157157),
    d=c(2,1,6,7,32,4,7157,4,6157,10,11,12157,9,12157,9,9,10157,4128128,86108,6,7,9,10,12)
    行程=C(97197141662133041662011346216206256756753784396757244726753787245633306100561040511346254394725563)
    x=c(697746.6696929.6696748.8696748.8696748.8696748.8694906.4694906.4694906.4694906.4696769.4696769.4696769.4698802.2698802.2698802.2698802.2698802.2698900.5698900.5698900.5698900.5699686.7696822.0696822.0696822.0696822.0698250.7702314.77000907.1702839.5702839.5694518.9694518.9694518.9694518.9694518.9694518.9694518.9694518.9694518.9694518.9694518.9页)
    lat.x=c(9312405931105193083389308338930833893708793070879307087930708793070879305947930594793059479304338930433893043893043893043389304338930231493023149306300930308093030809303080930942393207338932130293226199322619930192193019219301921930192193019219301921930192193019219301921)
    Y=C(696929.6697746.6694906.4696769.4696769.4698250.7696748.8696748.8696769.4694518.9696748.9696748.8694906.4694518.9698900.5699686.7696822.0694518.9698802.2696822.0694518.9698802.2698802.2698802.2698802.2698900.5694518.96748.8702839.57002839.57002314.77000907.16994907.16994906.4696769.4696769.4698802.2698900.2698900.2698900.4698900.4698802.46969696.5696822.0条)
    lat.y=c(9311051931240593070879305947930942393083389305947933019219308389307087930192193032314930630093030809301921930338930308093019219303389304338930231493019219308389322619932261993207338932130293070879305947930433893023149303080)
    

    df包含以下字段:
    o:trips的起源
    d:旅行目的地
    trip:number of trips betweenoandd
    lon.x:经度原点区
    lat.x:latitude of origin zone
    lon.y:目的地经度zone
    lat.y:latitude of destination zone

    目前,我可以使用geom_segmentggplot2package:

    库(ggplot2)
    
    ggplot()图+
    geom_段(数据=df,aes(x=lon.x,y=lat.x,xend=lon.y,yend=lat.y,size=trip)
    color=“blue”,alpha=0.5,show.legend=true,
    位置=位置闪避2(宽度=100))。+
    缩放\大小\连续(范围=C(0,5),断纸=C(300,600,900,1200),
    limits=c(100,1200),name=“人员出行/天(超过100次出行)”)+
    主题(legend.key=element矩形(colour=“transparent”,fill=alpha(“black”,0)))+
    参考线(尺寸=参考线图例(override.aes=列表(alpha=1.0)))+
    几何点(数据=df,aes(x=lon.x,y=lat.x),pch=16,尺寸=2.4)
    

    问题是从od和从do的每一行都重叠。我更喜欢根据中心线绘制被回避的路段,以便正确地可视化出行总数,并查看区域对之间的出行平衡。

    所需结果的示例如下所示。

    不一定要显示虚线中心线(我只是把它放在显示余额的地方)。也最好按方向改变颜色,例如顺时针方向为红色,逆时针方向为蓝色。如果方向可以用颜色显示,则不需要箭头。

    我找到了一些例子来解决这个问题,但是目前我无法取得理想的结果。

    坐标偏移量的计算 在这个例子中,为每个方向设置偏移量并不是那么容易,因为我有大约80个区域,结果是6400对区域。 offset geom_segment in ggplot

    位置闪避2功能 它说我可以在widthusing variable中设置段之间的边距,但是如果我使用tripin it,它会返回错误。此外,还不清楚应该为适当的偏移量设置多少值,以使段跟随中心线。 https://ggplot2.tidyverse.org/reference/position ou dodge.html

    geom_curveandarrow>
    也可以用曲线画线,这样就可以解决上述问题。然而,曲线段在观察一个图形中的运动时是混乱的。箭头也有点难以看到方向,因为箭头的形状不锋利,尽管我改变了它的样式。

    color=variableandposition=dodge
    我还尝试了spread/collectthedfto get new variabledirectionand to delete od pairs in opposite direction so that I thought I can easyly dodge segments usingcolor=directionandposition=dodgeinggplot2,但是它没有正常工作(segments are still overlapped).下面是一个小例子。

    o d trip direction lon.x lat.x lon.y lat.y
    1 2 971时钟697746.6 9312405 69696929.6 9311051
    2 1 300防锁696929.6 9311051 697746.6 9312405
    4 6 416时钟696748.8 9308338 694906.4 9307087
    4 7 621防锁694906.4 9307087 696748.8 9308338
    

    我非常感谢你的想法,以获得精心设计的数字。< BR> 另请参见下图以获取spider network的实际使用情况。 .

    这是我正在使用的数据帧:

    df <- data.frame(O=c(1,2,4,4,4,6,6,6,7,7,7,9,9,9,9,10,10,10,11,12,12,12,32,86,108,128,128,157,157,157,157,157),
    D=c(2,1,6,7,32,4,7,157,4,6,157,10,11,12,157,9,12,157,9,9,10,157,4,128,128,86,108,6,7,9,10,12),
    trip=c(971,971,416,621,330,416,620,1134,621,620,625,675,675,378,439,675,724,472,675,378,724,563,330,610,405,610,405,1134,625,439,472,563),
    lon.x=c(697746.6,696929.6,696748.8,696748.8,696748.8,694906.4,694906.4,694906.4,696769.4,696769.4,696769.4,698802.2,698802.2,698802.2,698802.2,698900.5,698900.5,698900.5,699686.7,696822.0,696822.0,696822.0,698250.7,702314.7,700907.1,702839.5,702839.5,694518.9,694518.9,694518.9,694518.9,694518.9),
    lat.x=c(9312405,9311051,9308338,9308338,9308338,9307087,9307087,9307087,9305947,9305947,9305947,9304338,9304338,9304338,9304338,9302314,9302314,9302314,9306300,9303080,9303080,9303080,9309423,9320738,9321302,9322619,9322619,9301921,9301921,9301921,9301921,9301921),
    lon.y=c(696929.6,697746.6,694906.4,696769.4,698250.7,696748.8,696769.4,694518.9,696748.8,694906.4,694518.9,698900.5,699686.7,696822.0,694518.9,698802.2,696822.0,694518.9,698802.2,698802.2,698900.5,694518.9,696748.8,702839.5,702839.5,702314.7,700907.1,694906.4,696769.4,698802.2,698900.5,696822.0),
    lat.y=c(9311051,9312405,9307087,9305947,9309423,9308338,9305947,9301921,9308338,9307087,9301921,9302314,9306300,9303080,9301921,9304338,9303080,9301921,9304338,9304338,9302314,9301921,9308338,9322619,9322619,9320738,9321302,9307087,9305947,9304338,9302314,9303080))
    

    df包含以下字段:
    O:出行来源
    D:旅行目的地
    trip:之间的行程数oD
    lon.x:起始区经度
    lat.x:起源区格
    lon.y:目的区经度
    lat.y:目的地等级

    目前,我可以使用下面的脚本绘制下图geom_segment在里面ggplot2包裹:

    library(ggplot2)
    
    ggplot() +
      geom_segment(data = df, aes(x = lon.x, y = lat.x, xend = lon.y, yend = lat.y, size = trip),
                   color = "blue", alpha = 0.5, show.legend = TRUE,
                   position = position_dodge2(width = 100)) +
     scale_size_continuous(range = c(0, 5), breaks = c(300, 600, 900, 1200),
                           limits = c(100, 1200), name = "Person trips/day (over 100 trips)") +
     theme(legend.key = element_rect(colour = "transparent", fill = alpha("black", 0))) + 
     guides(size = guide_legend(override.aes = list(alpha = 1.0))) +
     geom_point(data = df, aes(x = lon.x, y = lat.x), pch = 16, size = 2.4)
    

    enter image description here

    问题是每行来自

    enter image description here


    Offset geom_segment in ggplot


    widthhttps://ggplot2.tidyverse.org/reference/position_dodge.html

    geom_curvearrow

    color=variableposition=dodge
    spread/gatherdirectioncolor=direction

    O   D trip  direction    lon.x   lat.x    lon.y   lat.y
    1   2  971  clock     697746.6 9312405 696929.6 9311051
    2   1  300  anticlock 696929.6 9311051 697746.6 9312405
    4   6  416  clock     696748.8 9308338 694906.4 9307087
    4   7  621  anticlock 694906.4 9307087 696748.8 9308338
    


    1 回复  |  直到 6 年前
        1
  •  2
  •   Tyr Wiesner-Hanks    6 年前
    # make a dummy "clockwise" variable for now
    df$clockwise = df$O > df$D
    # angle from coordinates of stations
    df$angle = atan((df$lat.y - df$lat.x)/(df$lon.y - df$lon.x))
    # offsets from cos/sin of orthogonal angle
    # scale the distance of the offsets by the trip size so wider bars offset more
    # offset them one way if the trip is clockwise, the other way if not clockwise
    df$xoffset = cos(df$angle - pi/2) * df$trip/5 * (2 * df$clockwise - 1)
    df$yoffset = sin(df$angle - pi/2) * df$trip/5 * (2 * df$clockwise - 1)
    
    ggplot() +
      geom_segment(data = df, aes(x = lon.x + xoffset, y = lat.x + yoffset, xend = lon.y + xoffset, yend = lat.y + yoffset, size = trip, color = clockwise),
                   alpha = 0.5, show.legend = TRUE) +
      scale_size_continuous(range = c(0, 5), breaks = c(300, 600, 900, 1200),
                            limits = c(100, 1200), name = "Person trips/day (over 100 trips)") +
      theme(legend.key = element_rect(colour = "transparent", fill = alpha("black", 0))) + 
      guides(size = guide_legend(override.aes = list(alpha = 1.0))) +
      geom_point(data = df, aes(x = lon.x, y = lat.x), pch = 16, size = 2.4) +
      coord_fixed()
    

    Sample plot with above code