Как нарисовать направляющую линию на сгенерированном gnuplot cdf? - PullRequest
3 голосов
/ 24 января 2012

На работе есть набор значений с плавающей запятой, для которых я сортирую и вычисляю CDF и строю графики в gnuplot.Я хотел бы нарисовать линию, показывающую, где находятся пороги 80% и 90% CDF, то есть линия, идущая слева от отметки 0,8 года, касающаяся графика, а затем опускающаяся до того значения, которое может быть,Это должно помочь направить взгляд зрителя.

Данные генерируются автоматически, и я делаю несколько графиков, поэтому я не хочу каждый раз вручную создавать эти линии.

Тривиально нарисовать горизонтальную стрелку, проходящую по всему графику, тривиально.в точках 0 и 0,9, но я не понимаю, как определить, где должна быть проведена вертикальная линия.Вот aq / a относительно рисования стрелок: 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

Есть идеи?

Ответы [ 2 ]

4 голосов
/ 26 января 2012

Вот мой дубль (с использованием процентильных рангов), который предполагает, что доступен только одномерный ряд измерений (ваш столбец озаглавлен 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 (ах ... радость от магических чисел!) на желаемую.(в данном случае 0,9).

Некоторые пояснения по поводу приведенного выше кода:

  1. Я создал искусственный набор данных, который был сохранен на диске.
  2. 80-й процентильвычисляется с использованием awk, но перед этим нам нужно
    1. удалить заголовок, сгенерированный с помощью table (первые четыре строки);(мы могли бы попросить awk начать с 5-й строки, но давайте продолжим.)
    2. сохранить только второй столбец;
    3. отсортировать записи.
  3. Команда awk для вычисления 80-го процентиля требует усечения, что делается в соответствии с рекомендациями здесь .(В R я просто использовал бы функцию, такую ​​как trunc(rank(x))/length(x), чтобы получить процентильные ранги.)

Если вы хотите сделать R выстрел, вы можете смело заменить эту длинную серию sed / awkкоманды с вызовом R, такие как

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

при условии, что rnd.dat находится в вашем домашнем каталоге.


Sidenote: И если вы можете жить без 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)

enter image description here

0 голосов
/ 24 января 2012

Вы можете использовать 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 и 90% значения максимального значения y. Это может выглядеть примерно так:

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_min, x_max и y_max первый или второй столбец Data.csv.
  2. Проверьте, больше ли текущий первый столбец, чем текущий x_min, если это так, задайте x_min значение текущего первого столбца.
  3. Сделайте эквивалент для x_max и 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 не наткнулся на них ...

В конце концов вы должны получить сюжет вроде этого:

enter image description here

Зеленая линия отмечает 90-процентное значение максимального значения y.

...