如何在gnuplot中使用第三个变量作为线性拟合的拟合范围

how to use 3rd variable as fitting range in linear fit in gnuplot

我对 gnuplot 中的数据拟合有一些疑问。假设我的数据格式如下数据示例:test.txt

#   x       y       y_unc
1   0.20124531  2415.58 8.25706
2   0.20516169  2416.44 8.20651
3   0.21008456  2418.48 8.12084
4   0.21531272  2420.98 8.14102
5   0.22070909  2423.81 8.08436
6   0.2259568   2426.22 8.11353
7   0.23033106  2426.90 8.10172
8   0.23536205  2428.67 8.12772
9   0.24108887  2431.43 8.0769
10  0.24623346  2433.40 8.10201
11  0.252087    2436.33 8.19167
12  0.25853813  2439.53 8.14111
13  0.2634114   2441.27 8.14649
14  0.26842701  2442.58 8.19902
15  0.27422249  2444.09 8.25536
16  0.2799958   2447.22 8.32832
17  0.28573883  2449.42 8.37259
18  0.29226887  2452.35 8.34731
19  0.29696763  2453.71 8.32749
20  0.3020314   2454.80 8.40804
21  0.30853319  2457.60 8.3655
22  0.31335223  2459.26 8.41802
23  0.31937134  2461.96 8.4152
24  0.32383776  2461.80 8.45517
25  0.32963562  2464.02 8.49144
26  0.33469725  2465.15 8.37373
27  0.34041607  2467.62 8.30546
28  0.34591591  2469.44 8.30957
29  0.35146141  2471.29 8.37891
30  0.35608864  2471.50 8.30454
31  0.36138475  2472.98 8.31596
32  0.36773384  2476.24 8.43088
33  0.37238193  2476.59 8.34855
34  0.37814891  2478.86 8.26447
35  0.38311863  2479.65 8.28821
36  0.38847184  2481.35 8.25968
37  0.39456666  2484.14 8.21979
38  0.40007389  2486.06 8.16865
39  0.40610838  2488.30 8.25412
40  0.41157734  2490.10 8.29775
41  0.41630316  2491.59 8.31229
42  0.42112446  2492.40 8.26294
43  0.42697787  2494.75 8.32757
44  0.43137014  2495.07 8.36824
45  0.43700123  2496.25 8.46014
46  0.4422034   2497.68 8.45171
47  0.44765294  2500.41 8.42395
48  0.45317519  2502.29 8.48215
49  0.45835781  2503.81 8.50099
50  0.46392608  2505.78 8.61147
51  0.46943402  2508.04 8.60481
52  0.47533679  2510.15 8.58076
53  0.47967601  2510.77 8.6058
54  0.48523116  2513.11 8.63744
55  0.49090195  2515.74 8.8106
56  0.49617493  2517.32 8.8445
57  0.50119078  2518.77 8.87158
58  0.5066849   2520.57 8.93972
59  0.51132584  2522.25 8.91477
60  0.51644492  2524.03 8.89287
61  0.52197838  2526.33 9.00516
62  0.52705693  2528.27 8.92575
63  0.53193879  2529.73 8.95115
64  0.53704453  2531.44 8.99157
65  0.54210413  2532.46 9.03761
66  0.54626262  2533.34 9.00458
67  0.55056 2534.07 8.99342
68  0.55507934  2535.02 9.04953
69  0.55982471  2536.35 8.97597
70  0.56411815  2536.96 9.01189
71  0.56895626  2537.75 9.01932
72  0.57330275  2539.28 8.99917
73  0.57795715  2540.63 8.98475
74  0.58263767  2541.96 9.01778
75  0.58747137  2543.59 9.08297
76  0.59117234  2543.47 9.07999
77  0.59538865  2543.54 9.11839
78  0.59938073  2544.33 9.1549
79  0.60377049  2545.28 9.18278
80  0.60801435  2545.99 9.17474
81  0.61249495  2547.23 9.21996
82  0.61721373  2548.98 9.13147
83  0.62135947  2549.96 9.15198
84  0.6255244   2550.66 9.09919
85  0.629843    2551.9      9.15456
86  0.63427138  2553.34 9.21929
87  0.6376698   2552.96 9.19235
88  0.6422739   2554.31 9.24774
89  0.6468153   2555.74 9.1766
90  0.65102458  2556.53 9.22202
91  0.65579379  2558.13 9.16892
92  0.66031909  2559.52 9.20696
93  0.66545904  2561.28 9.29657
94  0.66935432  2561.9      9.23281
95  0.67299354  2562.15 9.28052
96  0.67770863  2564.20 9.37245
97  0.68189645  2565.98 9.48318
98  0.68605471  2566.81 9.56233
99  0.69018805  2567.83 9.59128
100 0.69424725  2568.67 9.63816

我尝试将第 2 列中的数据与第 3 列中的数据进行拟合。到目前为止,我可以使用以下代码进行拟合

 # Fitting data from file 

reset session 
set terminal qt size 800,480
set key left

FILE = 'test.txt'

# fit function

f(x) = a*x+b

fit [0.25:0.58] f(x) FILE u 2:3  via a,b

chi2=(FIT_STDFIT*FIT_STDFIT)

# setting label 
set label 1 'Fit Parameters' left at graph 0.7, graph 0.95 font "arial,15"
set label 2 sprintf("y= %.2fx + %.2f", a,b)left at graph 0.7, graph 0.90 font "arial,10"
set label 3 sprintf("a = %.2f %.2s %.2f",a,'±',a_err) left at graph 0.7, graph 0.86 font "arial,10"
set label 4 sprintf("b = %.2f %.2s %.2f",b,'±',b_err) left at graph 0.7, graph 0.82 font "arial,10"
set label 5 sprintf("ndf = %.2f ",  FIT_NDF) left at graph 0.7, graph 0.78 font "arial,10"
set label 6 sprintf("{/Symbol c}^2/ndf = %.2f ", chi2) left at graph 0.7, graph 0.74 font "arial,10"

# setting label box
set arrow 1 nohead at 0.51, 2755 to 0.75, 2755
set obj 10 rect at 0.63, 2710 size 0.25, 160
set obj 10 fillstyle empty border -1 front

# setting range
set xrange [0:0.8]
set yrange [2200:2800]
set ytics nomirror
set y2range [-50:300]
set y2tics 
set x2zeroaxis lt -1
set xlabel 'x-axis'
set ylabel 'y-axis'
set y2label 'residual'

# plotting 

plot FILE u 2:3:4 w yerr pt 7  lc rgb 'black' ti 'data',\
[0:0.58] f(x) w l lw 2 lc rgb 'red' ti 'fit',\
[0.25:0.58] FILE u 2:(f()-) pt 1 axes x1y2  ti 'residual'

# end code

并且使用测试数据我可以得到这个结果:

我的主要问题是:是否可以使用第三个变量,例如第 1 列中的行号作为拟合范围,而不是使用 x 值?例如,使用 [1:5] 来拟合前 ​​5 个数据,而不是使用 [0.20:0.22].

关于我上面的代码的其他问题,我将残差与拟合一起绘制,但我想将残差图限制在拟合数据内。使用上面的代码,绘制了整个数据的残差,当 运行 此代码时,我收到警告:“忽略非采样数据中的样本范围”。有什么办法可以解决这个问题吗?

最后一个,有没有更简单的方法来在图中打印拟合参数而不是使用标签?

据我了解,您有几个问题:

  1. 将一列与另一列相比较,同时通过第三列限制范围
  2. 用拟合结果简化标签
  3. 避免警告:“忽略非样本数据中的样本范围”

ad 1:写一个过滤函数,例如myRange(colD,colR,min,max) 其中 returns NaN 超出了所需的范围。 colD 是数据列,colR 是范围列,min,max 是范围的界限。

广告 2: 您可以在标签中使用换行符 \n 并使用增强文本。检查 help enhanced。您可以使用 set style textbox 制作一个框,可能不适用于所有终端,请选中 help textbox。仍然有点混乱,但肯定比绘制许多手动放置的标签、箭头和框要简单。

广告 3: 再次通过您的过滤功能限制您的剧情(参见广告 1)

所以,下面的代码:

  1. 绘制整个范围内的数据
  2. 在有限范围内拟合数据,受第 3 列限制
  3. 绘制给定范围内的拟合,此处:[0:0.58]
  4. 在有限范围内绘制残差,受第​​ 3 列限制
  5. 放置带有结果的标签

也许有更简单的解决方案,我目前还不知道。

代码:

### limit fit and plotting range via 3rd column
reset session

$Data <<EOD
#   x       y           y_unc
1   0.20124531  2415.58 8.25706
2   0.20516169  2416.44 8.20651
3   0.21008456  2418.48 8.12084
4   0.21531272  2420.98 8.14102
5   0.22070909  2423.81 8.08436
6   0.2259568   2426.22 8.11353
7   0.23033106  2426.90 8.10172
8   0.23536205  2428.67 8.12772
9   0.24108887  2431.43 8.0769
10  0.24623346  2433.40 8.10201
20  0.4         2500    8.0         # just added to show the larger range
30  0.5         2560    8.0
EOD

# filter function
myRange(colD,colR,min,max) = column(colR)>=min && column(colR)<=max ? column(colD) : NaN

# fit function
f(x) = a*x+b
fit f(x) $Data u (myRange(2,1,1,5)):3  via a,b
chi2=(FIT_STDFIT*FIT_STDFIT)

# setting label 
set label 1 at graph 0.7, graph 0.95 boxed \
        sprintf("%s\n%s\n%s\n%s\n%s\n%s", \
        "{/'Arial':Bold=14 Fit Parameters}", \
        sprintf("y= %.2fx + %.2f", a,b), \
        sprintf("a = %.2f %.2s %.2f",a,'±',a_err), \
        sprintf("b = %.2f %.2s %.2f",b,'±',b_err), \
        sprintf("ndf = %.2f ",  FIT_NDF), \
        sprintf("{/Symbol c}^2/ndf = %.2f ", chi2))
        
set style textbox border
set key left

# setting range
set xlabel 'x-axis'
set xrange [0:0.8]

set ylabel 'y-axis'
set yrange [2200:2800]
set ytics nomirror

set y2label 'residual'
set y2range [-50:300]
set y2tics 
set x2zeroaxis lt -1

plot $Data u 2:3:4 w yerr pt 7  lc rgb 'black' ti 'data',\
    [0:0.58] f(x) w l lw 2 lc rgb 'red' ti 'fit',\
    $Data u (myRange(2,1,1,5)):(f()-) pt 1 axes x1y2  ti 'residual'
### end of code

结果: