[英]How to plot a tree/graph/web with weighted edges in Gnuplot?
我正在按照此处的讨论在 gnuplot 中绘制一棵树( How to plot tree/graph/web data on gnuplot? )。 但是,我想包括树的边权重,即对于每个边,我都有一个代表边权重的数字(例如 10、20、30、40)。 下图以红色显示了我想要在 gnuplot 中 plot 的边缘权重(我使用 power point 添加了这个)。
谁能告诉我如何在 gnuplot 中使用权重计算 plot 边?
对于您在问题中提到的答案,我建议稍作改动。 假设顶点的坐标存储在文件pnts.dat
,如下所示:
0 5 10
1 20 20
2 15 15
3 30 30
4 40 10
在此,第一列记录相应的标签,而第二列和第三列分别包含x坐标和y坐标。
可以在单独的文件edges.dat
边定义为:
0 1 30 0 1
1 2 40 0 -2
1 4 20 0 1
1 3 10 0 1
在这里,前两列包含点索引(它们指向pnts.dat
的第一列)。 第三列记录特定边缘的权重。 最后,最后两列包含所生成的关联标签的x,y位移。
这样,Gnuplot脚本可能看起来像:
set xr [0:50]
set yr [0:50]
set size square
flePnts = 'pnts.dat'
fleEdges = 'edges.dat'
loadEdges = sprintf('< gawk '' \
FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
{printf "%%f\t%%f\n%%f\t%%f\n\n", x[$1], y[$1], x[$2], y[$2];} \
'' %s %s', flePnts, fleEdges);
loadWeights = sprintf('< gawk '' \
FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
{printf "%%f\t%%f\t%%s\n", (x[$1]+x[$2])/2 + $4, (y[$1]+y[$2])/2 + $5, $3} \
'' %s %s', flePnts, fleEdges);
plot \
loadEdges using 1:2 with lines lc rgb "black" lw 2 notitle, \
flePnts using 2:3:(0.6) with circles fill solid lc rgb "black" notitle, \
flePnts using 2:3:1 with labels tc rgb "white" font "Arial Bold" notitle, \
loadWeights using 1:2:3 with labels tc rgb "red" center font "Arial Bold" notitle
loadEdges
命令调用gawk
,以便为所有边缘生成对应的x / y坐标对(由空行分隔) loadWeights
为每个边缘计算中间点,并在这些坐标上放置一个标签(考虑到所需的偏移量) 另外,如果要向边缘添加箭头,则必须执行以下步骤:
添加箭头样式:
set style arrow 1 head filled size screen 0.025,10,40 lc rgb "black" lw 2
用向量的 行更改命令
loadEdges using 1:2:3:4 with vectors arrowstyle 1 notitle, \\
下图显示了最终结果:
这是最终的代码:
set xr [0:50]
set yr [0:50]
set size square
set style arrow 1 head filled size screen 0.025,10,40 lc rgb "black" lw 2
flePnts = 'pnts.dat'
fleEdges = 'edges.dat'
loadEdges = sprintf('< gawk '' \
FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
{printf "%%f\t%%f\t%%f\t%%f\n\n", x[$1], y[$1], (x[$2]-x[$1]), (y[$2]-y[$1]);} \
'' %s %s', flePnts, fleEdges);
loadWeights = sprintf('< gawk '' \
FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
{printf "%%f\t%%f\t%%s\n", (x[$1]+x[$2])/2 + $4, (y[$1]+y[$2])/2 + $5, $3} \
'' %s %s', flePnts, fleEdges);
plot \
loadEdges using 1:2:3:4 with vectors arrowstyle 1 notitle, \
flePnts using 2:3:(0.6) with circles fill solid lc rgb "black" notitle, \
flePnts using 2:3:1 with labels tc rgb "white" font "Arial Bold" notitle, \
loadWeights using 1:2:3 with labels tc rgb "red" center font "Arial Bold" notitle
这是一个类似于@ewcz 解决方案的建议,即使用带有 x,y 坐标的 ID 列表和使用两个 ID 的连接列表。 但是,具有以下差异:
awk
或gawk
的gnuplot-only解决方案,因此与平台无关。 查找列表是使用 gnuplot 创建的,类似于此答案。dA
和相对长度dR
的偏移量( dR=0
:在连接器的中心, dR=-1
:在起点, dR=1
:在终点)。 因此,建议使用set size ratio -1
,例如旋转 45 度在图形中视觉上是 45 度。 数据: SO42447683.dat
# ID x y
0 5 10
1 20 20
2 15 15
3 30 30
4 40 10
# ID1 ID2 weight dA dR
0 1 30 7 0
1 2 40 20 0
1 4 20 0 0
1 3 10 0 0
脚本:(适用于 gnuplot>=5.0.0,没有选项textbox
它适用于 >=4.6.0)
### plot tree with different labels
reset
FILE = "SO42447683.dat"
set size ratio -1
set key noautotitle
set offsets 0.5,0.5,0.5,0.5
set angle degrees
set style textbox opaque noborder
IdIdxs = XYs = ' '
stats FILE u (IdIdxs=IdIdxs.sprintf("%s:%d ",strcol(1),$0), \
XYs=XYs.sprintf("%g %g ",$2,$3)) index 0 nooutput
Px(i) = real(word(XYs,2*i+1))
Py(i) = real(word(XYs,2*i+2))
getIdx(col) = (c0=strstrt(IdIdxs,sprintf(" %s:",strcol(col))), \
c1=strstrt(IdIdxs[c0+1:],' ')+c0, \
s0=IdIdxs[c0:c1], c2=strstrt(s0,':'), int(s0[c2+1:]))
getLxy(colA,colR) = (idx0=getIdx(1), x0=Px(idx0),y0=Py(idx0), \
idx1=getIdx(2), x1=Px(idx1),y1=Py(idx1), \
rm = sqrt((x1-x0)**2+(y1-y0)**2)*(column(colR)+1)*0.5, \
a = atan2(y1-y0,x1-x0)+column(colA), \
Ly = y0+rm*sin(a), Lx=x0+rm*cos(a))
plot FILE index 1 u (idx0=getIdx(1),x0=Px(idx0)):(y0=Py(idx0)): \
(idx1=getIdx(2),Px(idx1)-x0):(Py(idx1)-y0) w vec lw 2 lc rgb "black" nohead, \
'' index 0 u 2:3 w p pt 7 ps 4 lc rgb "white",\
'' index 0 u 2:3 w p pt 6 ps 4 lc rgb "black",\
'' index 0 u 2:3:1 w labels, \
'' index 1 u (getLxy(4,5)):(Ly):3 w labels tc rgb "red" boxed
### end of script
结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.