#python #matplotlib #gnuplot
#python #matplotlib #gnuplot
Вопрос:
У меня есть уникальный набор данных (количество строк и столбцов может варьироваться в зависимости от конкретного случая.)
0.0 0 0 0 0 0 0
0.5 0 0 0 0 0 0
2.0 156.626 156.626 138.354 138.354 138.354 138.354
2.5 156.626 156.626 138.354 138.354 138.354 138.354
4.0 287.268 287.268 289.808 289.808 271.829 276.304
4.5 287.268 287.268 289.808 289.808 271.829 276.304
6.0 418.931 426.263 418.933 426.259 273.572 273.559
6.5 418.931 426.263 418.933 426.259 273.572 273.559
8.0 417.211 417.21 417.207 417.211 417.207 417.212
8.5 417.211 417.21 417.207 417.211 417.207 417.212
Как вы видите, он имеет уникальную комбинацию набора данных (постоянный, а затем изменяемый, постоянный, а затем изменяемый.) Я хочу отобразить постоянный набор данных в виде сплошной прямой линии без какого-либо типа штриха, а данные, которые не находятся в прямой линии, будут иметь другой тип штриха.
Мне нужен скрипт (либо gnuplot, либо matplotlib), который может отображать данные в соответствии с прилагаемым рисунком.На этом рисунке я показал только три строки в качестве примера.
Я создал приведенный ниже скрипт gnuplot, который дает мне требуемый график (но он не дает мне горизонтальных линий, сплошных без какого-либо типа штриха.
CASE = "New.dat"
Xi=-2 ; Xf=22; Xs=1
AYf=500 ; AYs=100
reset
set terminal postscript eps enhanced size 20cm,20cm color solid lw 3 "Times-Bold" 40
set output "data.eps"
set multiplot
layout 1,1 rowsfirst
title "{/:Bold=40 }"
margins screen 0.15,0.85,0.11,0.950
spacing screen 0.00,0.03
set key spacing 1.2
set mxtics 2
set mytics 2
unset key
unset arrow
set arrow from Xi ,0.00 to Xf,000 nohead lw 3.5 lc rgb "blue" lt 0
set xrange [Xi:Xf]
set yrange [-50:AYf]
set key at graph 0.63, 0.95 font "Times-bold, 30"
set xtics Xi,Xs,Xf format ""
set ytics 0,AYs,AYf format "%g" font "Times-bold, 40"
plot CASE u 1:2 title "Path-1" w l lc 1 lw 3 dashtype 2 , CASE u 1:3 title "Path-2" w l lc 2 lw 3 dashtype 3 , CASE u 1:4 title "Path-3" w l lc 4 lw 3 dashtype 4 , CASE u 1:5 title "Path-4" w l lc 6 lw 3 dashtype 5, CASE u 1:6 title "Path-5" w l lc 7 lw 3 dashtype 6 , CASE u 1:7 title "Path-6" w l lc 9 lw 3 dashtype 9
Комментарии:
1. Какую версию gnuplot вы используете?
2. Это версия 5.2 patchlevel 2 последнее изменение 2017-11-01
Ответ №1:
В gnuplot я бы сделал это так. Нарисуйте свои данные дважды
with lines
и другой тип штриховки- и горизонтальные линии
with vectors
, но только если значение y не меняется.
Немного сложно различить пунктирные линии, потому что некоторые из них находятся друг над другом. Вам нужно немного оптимизировать это.
Код:
### plot intermittent horizontal lines
reset session
$Data <<EOD
0.0 0 0 0 0 0 0
0.5 0 0 0 0 0 0
2.0 156.626 156.626 138.354 138.354 138.354 138.354
2.5 156.626 156.626 138.354 138.354 138.354 138.354
4.0 287.268 287.268 289.808 289.808 271.829 276.304
4.5 287.268 287.268 289.808 289.808 271.829 276.304
6.0 418.931 426.263 418.933 426.259 273.572 273.559
6.5 418.931 426.263 418.933 426.259 273.572 273.559
8.0 417.211 417.21 417.207 417.211 417.207 417.212
8.5 417.211 417.21 417.207 417.211 417.207 417.212
EOD
set key top left
set datafile missing NaN # apparently necessary for gnuplot 5.2.2
plot for [i=2:7] $Data u 1:i w l lw 2 lc i-1 dt i title sprintf("Path %d",i-1),
for [i=2:7] y1=x1=NaN $Data u (x0=x1,x1=column(1),x0):(y0=y1,y1=column(i)):(x1-x0):(y0==y1?0:NaN) w vectors lw 4 lc i-1 nohead notitle
### end of code
Результат:
Комментарии:
1. Ваш трюк продуктивен, но я получаю вертикальные линии в конце каждой горизонтальной линии. Эти строки начинаются с x = 0 до высоты (значения по оси Y) следующей горизонтальной линии.
2. Я загрузил график, полученный из вашего скрипта.
3. какую версию gnuplot вы используете?
4. Это версия 5.2 patchlevel 2 последнее изменение 2017-11-01
5. Вы хотите, чтобы заголовок вручную, а не автоматический заголовок? Проверьте
help keyentry
. Или вы можете определить массивarray myTitle[6] = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr']
, а затем в команде plotfor [i=2:7] $Data u 1:i w l lw 2 lc i-1 dt i title myTitle[i-1]
Ответ №2:
Вычислите индексы, которые соответствуют плато и возрастающим сегментам ваших данных. Затем постройте его по сегментам. Это график для первого пути. Для построения всех путей вы можете использовать другой цикл for. Возможно, есть более простое решение, но это должно сработать.
# path data
x = np.array([0. , 0.5, 2. , 2.5, 4. , 4.5, 6. , 6.5, 8. , 8.5])
y = np.array([0., 0., 156.626, 156.626, 287.268, 287.268, 418.931, 418.931, 417.211, 417.211])
# indices of plateau and increasing
idx_plat = np.where(np.diff(y) == 0)[0]
idx_incr = np.where(np.diff(y) != 0)[0]
# color for first path
color = 'C0'
# text setup
texts = ['A', 'B', 'C', 'D', 'E']
off = 10 # y offset for text
# plot plateau and increasing segments in a loop
for i in range(len(idx_plat) - 1):
x_sub = x[idx_plat[i]:idx_plat[i 1]]
y_sub = y[idx_plat[i]:idx_plat[i 1]]
plt.plot(x_sub, y_sub, linestyle = '--', color = color)
# annotate text
plt.text(x_sub.mean(), y_sub[0] off, texts[i])
for j in range(len(idx_incr) - 1):
x_sub = x[idx_incr[j]:idx_incr[j 1]]
y_sub = y[idx_incr[j]:idx_incr[j 1]]
plt.plot(x_sub, y_sub, linestyle = '-', color = color)
# plot last segment twice with label to create legend
plt.plot(x_sub, y_sub, linestyle = '-', color = color, label = label)
plt.legend(loc = 'best')