在工作中有一组浮点值,我在gnuplot中排序并计算CDF并绘制。我想绘制一条线,显示CDF的80%和90%阈值在哪里,即从左边@0.8 y tic标记出来的一条线,触摸图形然后下降到任何值可能是。这有助于引导观众眼球。
数据是自动生成的,我制作了多个图,所以我不想每次都手工制作这些线。
在0.8和0.9 y值点绘制完全穿过绘图的水平箭头是微不足道的,但我不明白如何确定应绘制垂直线的位置。 这是一个q / a wrt绘制箭头:Gnuplot: Vertical lines at specific positions,但这些位置是先验已知的。
以下是一些示例数据(我的工作机器无法访问互联网,因此共享很难)
X Y
5.0 | 0.143
8.0 | 0.288
16.0 | 0.429
25.0 | 0.714
39.0 | 0.857
47.0 | 1.000
有什么想法吗?
答案 0 :(得分:4)
这是我的看法(使用百分位数排名),它只假设有一系列单变量测量值(您的列标题为X
)。您可能需要稍微调整它以使用预先计算的累积频率,但这并不是很困难。
# generate some artificial data
reset
set sample 200
set table 'rnd.dat'
plot invnorm(rand(0))
unset table
# display the CDF
unset key
set yrange [0:1]
perc80=system("cat rnd.dat | sed '1,4d' | awk '{print $2}' | sort -n | \
awk 'BEGIN{i=0} {s[i]=$1; i++;} END{print s[int(NR*0.8-0.5)]}'")
set arrow from perc80,0 to perc80,0.8 nohead lt 2 lw 2
set arrow from graph(0,0),0.8 to perc80,0.8 nohead lt 2 lw 2
plot 'rnd.dat' using 2:(1./200.) smooth cumulative
这会产生以下输出:
当然,您可以根据需要添加任意数量的百分位值;你只需要定义一个新的变量,例如perc90
,以及请求另外两个arrow
命令,并用所需的0.8
替换table
的每一次出现(啊......幻数的快乐!)(在这种情况下) ,0.9)。
关于上述代码的一些解释:
trunc(rank(x))/length(x)
生成的标头(前四行); (我们可以要求awk从第5行开始,但让我们继续。)Rscript -e 'x=read.table("~/rnd.dat")[,2]; sort(x)[trunc(length(x)*.8)]'
的函数来获得百分等级。)如果你想给R一个镜头,你可以通过调用R来安全地替换那长串的sed / awk命令,如
rnd.dat
假设您的主目录中有quantile
。
旁注:如果你可以没有gnuplot,这里有一些R命令来做这种图形(甚至没有使用x <- rnorm(200)
xs <- sort(x)
xf <- (1:length(xs))/length(xs)
plot(xs, xf, xlab="X", ylab="Cumulative frequency")
## quick outline of the 80th percentile rank
perc80 <- xs[trunc(length(x)*.8)]
abline(h=.8, v=perc80)
## alternative solution
plot(ecdf(x))
segments(par("usr")[1], .8, perc80, .8)
segments(perc80, par("usr")[3], perc80, .8)
函数):
{{1}}
答案 1 :(得分:0)
您可以使用awk
计算给定值的行。
如果你有一个像这样的数据文件Data.csv
:
0 1
1 4
2 9
3 16
4 25
5 36
6 49
7 64
8 81
9 100
你可以用
绘图plot "Data.csv" u 1:2 w l
现在,如果要在第二列的最大值的90%处绘制一条线(在本例中为90),则运行一个awk脚本。其目的是确定最小和最大x值以及最大y值的90%值。它可能看起来像这样:
awk '
{
if(x_min == "") {x_min = x_max = $1; y_max = $2};
if($1 > x_max) {x_max = $1};
if($1 < x_min) {x_min = $1};
if(y_max < $2) {y_max = $2}}
END {
print x_min, y_max * 0.9;
print x_max, y_max * 0.9
}' Data.csv
基本上它的作用如下:
x_min
是否存在以及是否未将x_min
,x_max
和y_max
设置为Data.csv
的第一列或第二列。x_min
,如果是这种情况,请将x_min
设置为当前第一列的值。x_max
和y_max
的等效项(注意:我们只需要第二列的最大值而不是最小值)在循环浏览数据文件后,打印结果如下:
x_min y_max * 0.9
x_max y_max * 0.9
为了在gnuplot中完成这项工作,我们从上面附加我们的脚本,如下所示:
plot "Data.csv" u 1:2 w l, \
"< awk '{if(x_min == \"\") {x_min = x_max = $1; y_max = $2}; if($1 > x_max) {x_max = $1}; if($1 < x_min) {x_min = $1}; if(y_max < $2) {y_max = $2}} END {print x_min, y_max * 0.9; print x_max, y_max * 0.9}' Data.csv" u 1:2 w l
请注意gnuplot脚本中的\"
。 "
需要为gnuplot转义,以免绊倒他们......
毕竟你应该得到这样的情节:
绿线表示最大y值的90%值。