Search code examples
graphgnuplot

Plotting data arranged in rows rather than columns


I have a rather simple data file which is arranged in rows. However, gnuplot prefers the data in columns and I don't know if there's a way to plot the data without preprocessing (which I'd like to avoid).

Here's the sample data:

Time;10;20;30;40;50
Mag;100;200;400;750;950
Att;120;280;550;790;350
Sol;210;820;550;970;530

It's easy to plot the data if it would be laid out in columns:

set datafile separator ";"
set key autotitle columnheader
$DATA << EOD
Time;Mag;Att;Sol
10;100;120;210
20;200;280;820
30;400;550;550
40;750;790;970
50;950;350;530
EOD
plot $DATA using 1:2 w l, \
  '' using 1:3 w l, \
  '' using 1:4 w l

This is how the sample data is supposed to render:

sample image

Is there a way gnuplot can handle the data file laid out in rows? I tried using matrix but couldn't get the expected result. Any tips appreciated of how to solve this.


Solution

  • In general, gnuplot likes data in columns but not in rows.

    The simplest way to plot your data with gnuplot is to transpose your data. I can understand that you do not want to modify your data files or preprocess them with an external tool. Linux users probably have such tools like awk, sed, etc... installed by default, Windows users typically not. Unfortunately, gnuplot has no transpose function. But well, you can also do it with gnuplot (platform-independently), maybe a bit cumbersome, but it works.

    Script: (works with gnuplot>=5.0.0)

    ### plotting data in rows --> transpose data first
    reset session
    
    $Data <<EOD
    Time;10;20;30;40;50
    Mag;100;200;400;750;950
    Att;120;280;550;790;350
    Sol;210;820;550;970;530
    EOD
    
    set datafile separator ";"
    
    # transpose data
    stats $Data u 0 nooutput   # get the number of columns into STATS_columns
    maxCol = STATS_columns
    set print $Transposed
        do for [i=1:maxCol] {
            stats $Data u ($0==0? Line=strcol(i) : Line=Line.';'.strcol(i)) nooutput
            print Line
        }
    set print
    
    set key autotitle columnheader
    set key top left
    
    plot for [col=2:4] $Transposed using 1:col w l
    ### end of script
    

    Result:

    enter image description here

    Addition:

    With gnuplot>=5.4.0 you can shorten the transposing a bit. It uses the EXPERIMENTAL feature plot ... w table if <condition>, check help with table.

    Script: (works with gnuplot>=5.4.0, June 2020)

    ### plotting data in rows --> transpose data first
    reset session
    
    $Data <<EOD
    Time;10;20;30;40;50
    Mag;100;200;400;750;950
    Att;120;280;550;790;350
    Sol;210;820;550;970;530
    EOD
    
    set datafile separator ";"
    
    # transpose data
    stats $Data u 0 nooutput   # get the number of columns into STATS_columns and number of rows into STATS_records
    set table $Transposed
        plot for [i=1:STATS_columns] $Data u ($0==0? Line=strcol(i) : Line=Line.';'.strcol(i)) w table if $0==STATS_records-1
    unset table
    print $Transposed
    
    set key autotitle columnheader
    set key top left
    
    plot for [col=2:4] $Transposed using 1:col w l
    ### end of script
    

    The datablock $Transposed will look like this and the graph output is the same as above.

    Time;Mag;Att;Sol
    10;100;120;210
    20;200;280;820
    30;400;550;550
    40;750;790;970
    50;950;350;530