Есть ли способ загрузить данные из файла в массив Gnuplot? Я работаю с программой, которая предоставляет данные и вызывает gnuplot для создания графика. Теперь я пытаюсь установить xrange, чтобы установить верхний предел, когда данные во втором столбце наконец приближаются к нулю. Я много гуглил и пробовал разные методы. К сожалению безуспешно. Мне кажется, что наиболее многообещающим, но все еще не работающим подходом является импорт данных и их сохранение в массиве. Выдержка из кода приведена ниже:
stats '<datafile>' using 1:($2/1000.) nooutput
array myarray[STATS_records]
do for [i=STATS_records:0:-1] {
stats '<datafile>' using 1:($2/1000.) index i nooutput
myarray[i] = STATS_min_y
}
Выражение статистики в цикле вызывает ошибку, поскольку значения не найдены. Заранее благодарим вас за ваши предложения или альтернативные решения.
Из вашего текущего заголовка вопроса и фрагмента кода я предполагаю, что вы хотите прочитать данные, перевернутые в массив.
Теперь я пытаюсь установить xrange, чтобы установить верхний предел, когда данные во втором столбце наконец приближаются к нулю.
Это предложение заставляет меня думать, что, возможно, есть что-то еще, что вы не показываете и что может быть решено и без массивов. Может быть, мы столкнулись с xy-проблемой?
Следующий сценарий считывает столбец файла данных, преобразованный в массив.
Данные: SO76218289.dat
1 1.0
2 2.1
3 3.2
4 4.3
5 5.4
6 6.5
7 7.6
8 8.7
9 9.8
10 10.9
Скрипт: (требуется gnuplot>=5.2.0)
### read data from file reversed into array
reset session
FILE = "SO76218289.dat"
stats FILE u 0 nooutput # get number of rows
rowCount = STATS_records
array A[rowCount] # set array size
stats FILE u (A[int(rowCount-$0)] = $2) nooutput
print A
### end of script
Результат:
[10.9,9.8,8.7,7.6,6.5,5.4,4.3,3.2,2.1,1.0]
Добавление:
На самом деле, это была небольшая проблема с xy: вы просили поместить данные в массив, но фактическая цель состояла в том, чтобы ограничить диапазон x диапазоном, где y>0
. Это можно сделать проще. Используя тернарный оператор (отметьте help ternary
), значения x будут установлены на NaN
, если y<0
. Значение NaN
не будет отображаться и учитываться для x-autorange. Следовательно, в приведенном ниже примере диапазон x автоматически ограничивается [3:7]
. Если значения y могут стать ниже нуля в пределах ограниченного диапазона, а вы, тем не менее, хотите, чтобы линии были сведены к нулю, сценарий необходимо адаптировать.
Скрипт:
### limit xrange to data y>0
reset session
$Data <<EOD
1 -1.0
2 -0.5
3 0.5
4 3.0
5 2.0
6 1.0
7 0.5
8 -0.1
9 -0.5
10 -1.0
EOD
plot $Data u ($2>0 ? $1 : NaN):2 w lp pt 7 lc "red" notitle
### end of script
Результат:
Дополнение 2:
Просто для иллюстрации вы также можете ограничить данные диапазоном x, где y>0
, включая первую последовательность значений N
y<=0
. Для этого требуется stats
и более сложный оператор для понимания с использованием тернарных операторов и последовательной оценки (отметьте help operators binary
). Окончательное ограничение будет сделано every
(отметьте help every
).
Скрипт:
### limit x-range to values with y>0 and N values y<=0
reset session
$Data <<EOD
1 -1.0
2 -0.5
3 0.5
4 3.0
5 2.0
6 1.0
7 0.5
8 0.0
9 0.0
10 0.0
11 -1.0
12 -2.0
EOD
N = 3 # max. number of y-values <0 in a sequence
n0 = n1 = NaN
c = 0
stats $Data u ($2>0 && n0!=n0 ? n0=$0 : $2<=0 && n0==n0 && n1!=n1 ? c=c+1 : c=0, c==N ? n1=$0 : 0) nooutput
print n0,n1
plot $Data u 1:2 every ::n0::n1 w lp pt 7 lc "red"
### end of script
Некоторые пояснения:
n0
и n1
инициализируются как NaN
и c=0
.Каково значение:
($2>0 && n0!=n0 ? n0=$0 : $2<=0 && n0==n0 && n1!=n1 ? c=c+1 : c=0, c==N ? n1=$0 : 0)
y>0
и n0
равно NaN
(см. gnuplot: как сравнить с NaN?), то установите n0
на текущий индекс строки $0
, который будет в первый раз y>0
.y<=0
и n0
не NaN
, а n1
равно NaN
, увеличьте счетчик c
на 1, иначе сбросьте счетчик на c=0
.c
равно N
, установите n1
на текущий индекс строки $0
.В итоге: n0
содержит индекс строки с первым временем y>0
, а n1
содержит индекс строки, когда y
было N
-кратно <=0
(но только после того, как n0
было установлено какое-то значение).
Когда вы рисуете данные, вы просто ограничиваете их с помощью every ::n0::n1
.
В примере диапазон x будет ограничен [3:10], поскольку последние N=3 значения y равны y<=0.
Результат:
Спасибо за ваше дополнение. Это кажется гораздо более простым решением, и оно очень полезно. Вы, вероятно, правы, что это была проблема xy в определенной степени. Я постараюсь избежать этой ошибки в будущем. Тем не менее, мне кажется, что мое решение предлагает больше гибкости. Например, если я хочу включить первые n значений, которые равны нулю. Однако мне, возможно, придется больше работать с тернарными операторами, чтобы лучше понять их и их возможности.
@ManuelHochheim да, тернарные операторы часто очень полезны. Ваша (новая) задача по отображению первых n нулевых значений также может быть выполнена без массивов (с stats
и некоторым счетчиком). Но я согласен, массивы тоже могут быть полезны во многих случаях.
Большое спасибо! Это именно то, что я искал. Но, возможно, другим будет полезно, если я опубликую более расширенный фрагмент кода, чтобы прояснить, что я пытался сделать:
FILE = '<datafile>'
stats FILE u 0 nooutput
rowCount = STATS_records
array A[rowCount]
stats FILE u (A[int(rowCount-$0)] = $2) nooutput
do for [i=1:rowCount-1] {
if (int(A[i]) > 0) {
xoffset = rowCount - i
break
}
}
stats '<datafile>' u 1:($2/1000) nooutput
xmin = STATS_min_x
xmax = STATS_min_x + xoffset
# Set ranges and ticks
set xrange [xmin:xmax]
plot '<datafile>' using 1:($2/1000.)
В своем коде я пытаюсь найти точку, в которой мой столбец данных просто содержит нулевые значения. Он соответствующим образом регулирует xrange. Это работает для меня. Но если вы знаете лучшую версию, пожалуйста, дайте мне знать. Я был бы рад учиться у вас и улучшать свои навыки работы с gnuplot.
Итак, я немного лучше понимаю, что вы на самом деле хотите сделать. Но все еще нужны некоторые догадки, как я теперь понимаю: у вас есть некоторые данные, и вы хотите ограничить xrange так, чтобы значения y превышали 0
, верно? Что, если значения y окажутся ниже и выше нуля несколько раз?
Это правильно, что я хочу ограничить диапазон x таким образом, чтобы значения y в хвосте моих данных были больше 0. Значения меньше нуля в моем случае не имеют значения, поскольку я знаю, что мои значения всегда больше равны нулю.
Добро пожаловать в StackOverflow! Как выглядят ваши данные? Хорошо, два столбца, но есть ли в нем пустые строки или двойные пустые строки? Пожалуйста, опишите структуру вашего файла данных и приведите свернутый пример. Кроме того, похоже, вы хотите изменить порядок данных, верно?