如何在gnuplot生成的cdf上绘制引导线?

时间:2012-01-24 11:01:15

标签: r statistics gnuplot data-visualization cdf

在工作中有一组浮点值,我在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

有什么想法吗?

2 个答案:

答案 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

这会产生以下输出:

enter image description here

当然,您可以根据需要添加任意数量的百分位值;你只需要定义一个新的变量,例如perc90,以及请求另外两个arrow命令,并用所需的0.8替换table的每一次出现(啊......幻数的快乐!)(在这种情况下) ,0.9)。

关于上述代码的一些解释:

  1. 我生成了一个保存在磁盘上的人工数据集。
  2. 第80个百分点是使用awk计算,但在此之前我们需要
    1. 删除trunc(rank(x))/length(x)生成的标头(前四行); (我们可以要求awk从第5行开始,但让我们继续。)
    2. 仅保留第二列;
    3. 对条目进行排序。
  3. 计算第80百分位数的awk命令需要截断,这是按照建议here完成的。 (在R中,我只是使用类似Rscript -e 'x=read.table("~/rnd.dat")[,2]; sort(x)[trunc(length(x)*.8)]' 的函数来获得百分等级。)
  4. 如果你想给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}}

    enter image description here

答案 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

基本上它的作用如下:

  1. 检查x_min是否存在以及是否未将x_minx_maxy_max设置为Data.csv的第一列或第二列。
  2. 检查当前第一列是否大于当前x_min,如果是这种情况,请将x_min设置为当前第一列的值。
  3. 执行x_maxy_max的等效项(注意:我们只需要第二列的最大值而不是最小值)
  4. 在循环浏览数据文件后,打印结果如下:

    x_min y_max * 0.9
    x_max y_max * 0.9
    
  5. 为了在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转义,以免绊倒他们......

    毕竟你应该得到这样的情节:

    enter image description here

    绿线表示最大y值的90%值。