Create scientific plots using gnuplot

December 21st, 2013 | 2 Comments

After plotting the world several times we will concentrate on a smaller level this time. Ben Johnson was so kind to convert the part dealing with the USA of the 10m states and provinces data set from natural earth to something useful for gnuplot. The result is stored in the file usa.txt.

USA election

Fig. 1 Election results of single U.S. states. (code to produce this figure, USA data, election data)

Two double lines divide the single states. This allows us to plot a single state with the help of the index command. At the end of this post the corresponding index numbers for every state are listed.
In addition to the state border data we have another file that includes results from an example election and strings with the names of the states. The election result can be 1 or 2 – corresponding to blue and red. With the help of these two data sets we are able to create Fig. 1 and Fig. 2.
For drawing a single state in red or blue we first collect the results for every single state in the string variable ELEC. The stats command is suitable for this, because it parses all the data but doesn’t try to plot any of them. During the parsing of every line the election result stored in the second column will be added at the end of the ELEC variable.

stats 'election.txt' u 1:(ELEC = ELEC.sprintf('%i',$2))

In a second step we plot the state borders and color the states with the help of the ELECstring. ELEC[1:1] will return the election result for the state with the index 0.

plot for [idx=0:48] 'usa.txt' i idx u 2:1 w filledcurves ls ELEC[idx+1:idx+1],\
                    ''              u 2:1 w l ls 3

Alaska and Hawaii are then added with additional plot commands and the help of multiplot.

The data file with the election results includes also the names of the single states and a coordinates to place them. This allows us to put them in the map as well, as you can see in Fig. 2.

USA election

Fig. 2 Names and election results of single U.S. states. (code to produce this figure, USA data, election data)

The plotting of the state names is easily achieved by the labels plotting style:

plot for [idx=0:48] 'usa.txt' i idx u 2:1 w filledcurves ls ELEC[idx+1:idx+1],\
                    ''              u 2:1 w l ls 3,\
                    'election.txt'  u 6:5:3 w labels tc ls 3

At the end we provide the list with the index numbers and the corresponding states. If you want to plot a subset of states – as in Fig. 2 – you should adjust the xrange and yrange values accordingly.

0  Massachusetts
1  Minnesota
2  Montana
3  North Dakota
4  Idaho
5  Washington
6  Arizona
7  California
8  Colorado
9  Nevada
10 New Mexico
11 Oregon
12 Utah
13 Wyoming
14 Arkansas
15 Iowa
16 Kansas
17 Missouri
18 Nebraska
19 Oklahoma
20 South Dakota
21 Louisiana
22 Texas
23 Connecticut
24 New Hampshire
25 Rhode Island
26 Vermont
27 Alabama
28 Florida
29 Georgia
30 Mississippi
31 South Carolina
32 Illinois
33 Indiana
34 Kentucky
35 North Carolina
36 Ohio
37 Tennessee
38 Virginia
39 Wisconsin
40 West Virginia
41 Delaware
42 District of Columbia
43 Maryland
44 New Jersey
45 New York
46 Pennsylvania
47 Maine
48 Michigan
49 Hawaii
50 Alaska


  1. Jose-Maria Martin-Olalla says:

    Hi Hagen,

    Great stuff!!

    I am currently trying to take advantage of this post and I have two questions for you:

    1. I am trying to produce an US map with states colored by Time Zone. I follow your approach and define TZ in the way you define ELEC. It works fine. Only that my set of data from which TZ is obtained is ordered by FIPS code (mostly alfabetical) and it is not the way states are ordered in usa.txt.

    So when doing

    plot for [i=0:48] 'usa.txt' u 2:1 index i w l ls TZ[idx+1:idx+1]

    states and TZ end blended.

    Can I define a variable (let it be named fips) in gnuplot so that TZ[fips(idx):fips(idx)] would fix the inconstency?

    2. I need to produce bounduaries for countries and regions in Europe. I know you get yours from Natural Earth but I could not find the way to produce my bounduary files. Will you kindly provide any further information or link?

    [OS: Linux; able to parse files through sed, awk or imagemagick]

  2. Jose-Maria Martin-Olalla says:

    I ended up with the following sed script. Following the script provided by Hagen ( it is able to parse the csv file created by ogr2ogr into a decent data file for gnuplot:

    1d #delete first line
    s/^”POLYGON (\+//g #search and delete polygon
    s/^”MULTIPOLYGON (\+//g #search and delete multipolygon
    s/)\+,(\+/\n\n/g #in multipolygon, remove polygon-link. Also create new block.
    # Good or bad idea?
    s/)\+.*$/\n\#&1\n\n/g # comment out and store the additional information provided by NaturalEarth
    # insert two new lines to start a new gnuplot block.
    /^#/!s/,/\n/g #convert , into new line if the line is not a comment; intended to produce the two
    #column “longitude latitude” data.

    I have not the faintest idea on how NaturalEarth stores data and/or how ogr2ogr retrieves data. But the script worked for bounduaries, countries and time-zones.

    The last line failed to do its job through the script. Nonetheless it worked through the command line.

    I assume the script can be improved.