Как отображать данные по прямой линии и в разных стилях линий в зависимости от набора данных

#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
  

Это из скрипта theozh введите описание изображения здесь

Комментарии:

1. Какую версию gnuplot вы используете?

2. Это версия 5.2 patchlevel 2 последнее изменение 2017-11-01

Ответ №1:

В gnuplot я бы сделал это так. Нарисуйте свои данные дважды

  1. with lines и другой тип штриховки
  2. и горизонтальные линии 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'] , а затем в команде plot for [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')