A short demonstration using pkg-json with GNU Octave to plot a simplified two dimensional political “World Map” from public available JSON data provided by the NASA. The following code can be used, to easily visualize data divided by countries (e.g. population densities, health data, economic figures, tax, export, etc.).
The code at a glance
%% Step 1: Install and load pkg-json.if (isempty (pkg ("list","pkg-json")))pkg install "https://github.com/gnu-octave/pkg-json/archive/v1.0.0.tar.gz"endpkgloadpkg-json%% Step 2: Define a helper function to plot an individual country.function plot_country (name, color, countries, obj) idx =find (strcmp (name, countries));if (isempty (idx))error ("Country ''%s' not found.", name);end data_str = obj.data(idx){1}(10){1}; data_str = data_str((1+length("MULTIPOLYGON (((")):(end-3)); data_str =strsplit (data_str,")), ((");fori=1:length (data_str) data =textscan (data_str{i},"%f %f,");fill (data{:,1}, data{:,2}, color);hold on;endend%% Step 3: Download the public data set.json_str =urlread ("https://data.nasa.gov/api/views/yqhp-cuk8/rows.json?accessType=DOWNLOAD");%% Step 4: Import JSON data to GNU Octave.obj = jsondecode (json_str);%% Step 5: Extract the country names.countries =cell(length (obj.data),1);fori=1:length (obj.data) countries{i} = obj.data(i){1}(9){1};end%% Step 6: Plot all available countries with random color.fori=1:length (countries) plot_country (countries{i},rand (3,1), countries, obj)end
The code explained
Step 3: Using urlread it is really straight forward to import the data provided by the NASA into a string.
The jsondecode function can of course not know about the structure of the NASA map data itself, thus it is necessary to explore the imported data using Octave.
The first step is to simply output the content of obj, which is quite verbose and thus omitted here.
As JSON is a structured data format, most of the content is converted to Octave structures. A handy function to get an overview of Octave structures is fieldnames.
fieldnames (obj)
ans =
{
[1,1] = meta
[2,1] = data
}
A splitting into a meta and data section can be observed. Some further investigation of the meta section revealed, that it is not very useful for the purpose of plotting the world map, thus it is not further explained here.
On the other hand the data section contains the desired polygon edge data of the several country borders.
Step 5: For the sake of convenience, the names of the individual countries are exported into an cell array of strings.
countries =cell(length (obj.data),1);fori=1:length (obj.data) countries{i} = obj.data(i){1}(9){1};end
With this approach, it is easy to map a country name to an index in obj.data, which is examined in the following for “Japan”.
japan =find (strcmp (countries,"Japan"))usa =find (strcmp (countries,"United States of America"))
From this data about Japan, we are only interested in the 10th entry, defining the “MULTIPOLYGON” data about three larger Japanese islands (areas). The format is as follows:
MULTIPOLYGON (
((x1 y1, x2 y2, ...)) // Area 1
((x1 y1, x2 y2, ...)) // Area 2
...
)
Using some straight forward Octave instructions, this sub format of the JSON data can be further processed by Octave.
%% Extract the 10th data entry.data_str = obj.data(japan){1}(10){1};%% Strip start and end of the numerical data.data_str = data_str((1+length("MULTIPOLYGON (((")):(end-3));%% Split area data into individual cells of an array.data_str =strsplit (data_str,")), ((");
The data in the three cells is still of type “string” and can finally be converted using textscan for example.
Now the x,y-data for the edges of each area is available in numerical form and can be simply plotted by Octave’s fill function in the same loop.
fori=1:length (data_str) data =textscan (data_str{i},"%f %f,");fill (data{:,1}, data{:,2},"r");hold on;end
Step 2: All steps above can conveniently be abstracted into a single function plot_country, defined in the first code section of this notebook.
A second more simplified function call will look like this, where countries is obtained by Step 5 and obj by Step 4. "g" (= “green”) is the color that should used.
plot_country ("United States of America","g", countries, obj)
In Step 6 an example was given how all available countries can be plotted.