{"id":14527,"date":"2026-08-19T01:00:00","date_gmt":"2026-08-19T05:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=14527"},"modified":"2026-08-04T20:17:07","modified_gmt":"2026-08-05T00:17:07","slug":"data-analysis-with-gnuplot","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=14527","title":{"rendered":"Data analysis with gnuplot"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"14527\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p class=\"wp-block-paragraph\">When I was an undergraduate physics student in the early 1990s, we performed all kinds of data analysis. For some labs, we analyzed data by writing a custom program in FORTRAN. But for other labs, we could refactor the equations so that we could perform a&nbsp;<em>linear regression<\/em>&nbsp;on the data, which was easy to do in a spreadsheet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I\u2019m rediscovering another tool that I used at the time: gnuplot. This is a powerhouse for creating charts and graphs. But it can also perform line-fitting and other regression analysis. Let\u2019s take a look.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Linear data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For this test, I created some sample data that is&nbsp;<em>almost<\/em>&nbsp;a line, but has some slight variations in the data (like you might have with experimental deviation). I generated 9&nbsp;<em>x,y<\/em>&nbsp;pairs, from&nbsp;<em>x<\/em>&nbsp;= 1 to 9, and&nbsp;<em>y<\/em>&nbsp;from about 101 to about 109. To add some random variance in the&nbsp;<em>y<\/em>&nbsp;values, I used the&nbsp;<code>$RANDOM<\/code>&nbsp;variable from Bash:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ (for x in $(seq 9); do echo $x 10$x.$RANDOM; done) &gt; xy.dat\n\n$ cat xy.dat\n1 101.25622\n2 102.25919\n3 103.27729\n4 104.2294\n5 105.8165\n6 106.7244\n7 107.32100\n8 108.27283\n9 109.9938<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I wanted to have a reference to see what the&nbsp;<em>correct<\/em>&nbsp;linear regression values should be. I loaded the data into LibreOffice Calc and used&nbsp;<strong>Data &gt; Statistics &gt; Regression<\/strong>&nbsp;to perform a linear fit of the data. LibreOffice calculated the parameters as<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><em>y<\/em>\u2004=\u2004(100.163\u2005\u00b1\u20050.192)\u2005+\u2005(1.0595\u2005\u00b1\u20050.034)<em>x<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is, the&nbsp;<em>intercept<\/em>&nbsp;is 100.16&nbsp;<em>plus or minus<\/em>&nbsp;0.19, and the&nbsp;<em>slope<\/em>&nbsp;is 1.059&nbsp;<em>plus or minus<\/em>&nbsp;0.034. The \u201cplus or minus\u201d is also called the&nbsp;<em>standard deviation<\/em>, and is a typical way to show \u201cuncertainty\u201d in the values.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1101\" height=\"984\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/08\/libreoffice-linefit.png\" alt=\"\" class=\"wp-image-14530\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Linear analysis using gnuplot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s do the same analysis with the gnuplot program. gnuplot is an interactive program, and you type commands from the Linux terminal.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gnuplot\n\n    G N U P L O T\n    Version 6.0.3 patchlevel 3    last modified 2025-06-01 \n\n    Copyright (C) 1986-1993, 1998, 2004, 2007-2025\n    Thomas Williams, Colin Kelley and many others\n\n    gnuplot home:     http:\/\/www.gnuplot.info\n    faq, bugs, etc:   type \"help FAQ\"\n    immediate help:   type \"help\"  (plot window: hit 'h')\n\n    Terminal type is now qt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The gnuplot program can perform regression analysis. The algorithm is a standard method: it minimizes the sum of the squares between the data points and the function that you \u201cfit\u201d to the data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To start, you need to define a function that describes the data. In this case, the data is linear, so I can enter a formula for a line. I\u2019ve specified&nbsp;<em>i<\/em>&nbsp;for the intercept and&nbsp;<em>s<\/em>&nbsp;for the slope:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gnuplot&gt; f(x) = i + s * x<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, you can instruct gnuplot to perform a \u201cfit\u201d of the function to the data, using the&nbsp;<code>fit<\/code>&nbsp;command. Provide the name of the function (in this case, that\u2019s the&nbsp;<code>f(x)<\/code>&nbsp;function) and the name of the file that contains the&nbsp;<em>x,y<\/em>&nbsp;data. Also indicate the variables in the equation using the&nbsp;<code>via<\/code>&nbsp;keyword. gnuplot will perform an analysis and print the results:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gnuplot&gt; fit f(x) 'xy.dat' via i, s\niter      chisq       delta\/lim  lambda   i             s            \n   0 8.9033443626e+04   0.00e+00  4.04e+00    1.000000e+00   1.000000e+00\n   1 1.4504263892e+04  -5.14e+05  4.04e-01    1.315399e+01   1.404999e+01\n   2 9.4785384252e+01  -1.52e+07  4.04e-02    9.310936e+01   2.180155e+00\n   3 4.9191609003e-01  -1.92e+07  4.04e-03    1.001571e+02   1.060551e+00\n   4 4.9184258903e-01  -1.49e+01  4.04e-04    1.001634e+02   1.059561e+00\n   5 4.9184258903e-01  -4.97e-10  4.04e-05    1.001634e+02   1.059561e+00\niter      chisq       delta\/lim  lambda   i             s            \n\nAfter 5 iterations the fit converged.\nfinal sum of squares of residuals : 0.491843\nrel. change during last iteration : -4.966e-15\n\ndegrees of freedom    (FIT_NDF)                        : 7\nrms of residuals      (FIT_STDFIT) = sqrt(WSSR\/ndf)    : 0.265072\nvariance of residuals (reduced chisquare) = WSSR\/ndf   : 0.0702632\n\nFinal set of parameters            Asymptotic Standard Error\n=======================            ==========================\ni               = 100.163          +\/- 0.1926       (0.1923%)\ns               = 1.05956          +\/- 0.03422      (3.23%)\n\ncorrelation matrix of the fit parameters:\n                i      s      \ni               1.000 \ns              -0.889  1.000 <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s a lot of output! The output shows the iterations as gnuplot used different values. The&nbsp;<code>chisq<\/code>&nbsp;column indicates the&nbsp;<em>\u03c7<\/em><sup>2<\/sup>&nbsp;value, which is the sum of the squares of the&nbsp;<em>differences<\/em>&nbsp;between the data and the \u201cfit\u201d line. This converged after 5 iterations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below that, gnuplot shows the final parameters: the&nbsp;<em>intercept<\/em>&nbsp;is 100.163&nbsp;<em>plus or minus<\/em>&nbsp;0.1926, and the&nbsp;<em>slope<\/em>&nbsp;is 1.05956&nbsp;<em>plus or minus<\/em>&nbsp;0.03422. (Compare that to the values calculated by LibreOffice: the&nbsp;<em>intercept<\/em>&nbsp;was 100.16&nbsp;<em>plus or minus<\/em>&nbsp;0.19, and the&nbsp;<em>slope<\/em>&nbsp;was 1.059&nbsp;<em>plus or minus<\/em>&nbsp;0.034. These are the same values!)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Charting the results<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We can now chart the data using gnuplot. In the simplest case, we can use the&nbsp;<code>plot<\/code>&nbsp;command to create a chart of the&nbsp;<code>f(x)<\/code>&nbsp;function; gnuplot will fill in the values that it calculated the&nbsp;<em>i<\/em>&nbsp;and&nbsp;<em>s<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gnuplot&gt; plot f(x)<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/08\/linefit-gnuplot.png\" alt=\"\" class=\"wp-image-14524\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">But gnuplot can chart more than one thing at a time. Let\u2019s add the&nbsp;<em>x,y<\/em>&nbsp;data points to the chart. To do that, type a comma then add the other chart command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gnuplot&gt; plot f(x), 'xy.dat'              <\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/08\/linefit-gnuplot2.png\" alt=\"\" class=\"wp-image-14525\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I prefer that my&nbsp;<em>x<\/em>&nbsp;axis starts at zero, to make it easier for people to read the chart values and identify the intercept. To specify a range for the&nbsp;<em>x<\/em>&nbsp;axis, provide the start and end values in square brackets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gnuplot&gt; plot &#91;0:10] f(x), 'xy.dat'       <\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/08\/linefit-gnuplot3.png\" alt=\"\" class=\"wp-image-14526\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I love that gnuplot is so flexible. It does more than simple charting; it\u2019s also a scientific analysis tool. Explore the\u00a0<a href=\"http:\/\/gnuplot.info\/\">gnuplot website<\/a>\u00a0to learn what else you can do with gnuplot. For more about fitting functions to data, see the\u00a0<a href=\"http:\/\/gnuplot.info\/demo\/fit.html\">line fit demos<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>gnuplot can do more than chart data, it can also analyze data<\/p>\n","protected":false},"author":33,"featured_media":4295,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[100,5],"tags":[104,91],"class_list":["post-14527","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-command-line","category-linux","tag-command-line","tag-linux"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14527","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14527"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14527\/revisions"}],"predecessor-version":[{"id":14532,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14527\/revisions\/14532"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/4295"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14527"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14527"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14527"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}