3

在工作中有一组浮点值,我对其进行排序和计算 CDF 并在 gnuplot 中绘图。我想画一条线,显示 CDF 的 80% 和 90% 阈值在哪里,即从左侧进入的线 @ 0.8 y tic 标记,触摸图表,然后下降到任何可能的值. 这是为了帮助引导观众的视线。

数据是自动生成的,我制作了多个绘图,所以我不想每次都手工制作这些线条。

在 0.8 和 0.9 y 值点处绘制一个完全穿过绘图的水平箭头很简单,但我不明白如何确定应该在哪里绘制垂直线。这是 aq/a wrt 绘图箭头:Gnuplot:特定位置的垂直线,但这些位置是先验已知的。

这是一些示例数据(我的工作机器无法访问互联网,因此很难共享)

  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

有任何想法吗?

4

2 回答 2

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.9)替换每次出现的0.8(啊……神奇数字的乐趣!)。

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

  1. 我生成了一个人工数据集,该数据集保存在磁盘上。
  2. 第 80 个百分位是使用 awk 计算的,但在此之前我们需要
    1. table删除由(前四行)生成的标题;(我们可以要求 awk 从第 5 行开始,但让我们继续吧。)
    2. 只保留第二列;
    3. 对条目进行排序。
  3. 计算第 80 个百分位数的 awk 命令需要截断,按照此处的建议完成。(在 R 中,我会简单地使用一个函数trunc(rank(x))/length(x)来获取百分位数。)

如果你想给 R 一个机会,你可以安全地用对 R 的调用来替换一长串 sed/awk 命令,比如

Rscript -e 'x=read.table("~/rnd.dat")[,2]; sort(x)[trunc(length(x)*.8)]'

假设rnd.dat在您的主目录中。


旁注:如果你可以不使用 gnuplot,这里有一些 R 命令可以制作这种图形(即使不使用该quantile函数):

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)

在此处输入图像描述

于 2012-01-26T17:35:12.903 回答
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_max对and做等价y_max(注意:我们只需要第二列的最大值而不是最小值)

  4. 在我们遍历我们的数据文件后,打印结果如下:

    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%。

于 2012-01-24T14:14:03.900 回答