2

I have JSON file that looks something like this

{
    "data": [
    {
        "type": "SENIOR",
        "male": 350000.0,
        "female": 225000.0
    },
    {
        "type": "ENTRY",
        "male": 100000.0,
        "female": 40000.0
    },
    {
        "type": "MID",
        "male": 225000.0,
        "female": 150000.0
    }
    ]
}

and I need to create a bar plot with dynamic x fields, that are read from json.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{luacode}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{ifthen}

%%%%% Lua code %%%%%% \begin{luacode} local json = require("json") local file = io.open("mwe.json") tab = json.parse(file:read("*all")) file:close() \end{luacode}

\begin{document} % Number of labels \newcommand{\nrlabels}{\directlua{tex.print(table.getn(tab['data']))}}

% Create counter for loop through labels \newcounter{labelctr}\stepcounter{labelctr} \newcounter{totallabels} \setcounter{totallabels}{\nrlabels}\stepcounter{totallabels} \newcounter{onemorelabel}\setcounter{onemorelabel}{\value{totallabels}}\addtocounter{onemorelabel}{-1}

\begin{tikzpicture} \begin{axis}[ width = 0.85\textwidth, height = 8cm, %major x tick style = transparent, ybar=2\pgflinewidth, bar width=20pt, %ymajorgrids = true, ylabel = {Average Wage}, %symbolic x coords= {\whiledo{\value{labelctr} < \value{totallabels}}{\directlua{tex.print(tab['data'][\thelabelctr]['type'])}\ifthenelse{\value{labelctr}<\value{onemorelabel}}{,}{}\stepcounter{labelctr}}} symbolic x coords={SENIOR,ENTRY,MID} ] \addplot[fill=blue] coordinates {\whiledo{\value{labelctr} < \value{totallabels}}{(\directlua{tex.print(tab['data'][\thelabelctr]['type'])}, \directlua{tex.print(tab['data'][\thelabelctr]['male'])}) \stepcounter{labelctr}}}; \end{axis} \end{tikzpicture}

\end{document}

This is what I have so far. And I need something like thisenter image description here

Thanks..

Almic7
  • 131

1 Answers1

1

Combining How to plot data from json and Comma in x coord (interval) gives the MWE below.

The idea is to use tex.sprint to write the table in the correct format to the input stream, as if the table data was actually written in the .tex file. Then \pgfplotstableread can read the entire table at once.

For the plot this requires the options xticklabels from table and xtick=data. Each category has a separate \addplot command with the corresponding y index in the table.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\begin{document} %%%%% Lua code %%%%%% %% This prints the following table to the input stream: %% type male female %% SENIOR 350000.0 225000.0 %% ENTRY 100000.0 40000.0 %% MID 225000.0 150000.0

\expandafter\pgfplotstableread\directlua{ local json = utilities.json.load("groupeddata.json") tex.sprint("{\string\r") tex.sprint("type male female\string\r") for n, row in ipairs(json.data) do tex.sprint(row.type .. " " .. row.male .. " " .. row.female .. "\string\r") end tex.sprint("}") }\loadedtable

\begin{tikzpicture} \begin{axis}[ width = 0.85\textwidth, height = 8cm, ybar=2\pgflinewidth, area legend, bar width=20pt, ylabel = {Average Wage}, xticklabels from table={\loadedtable}{type}, xtick = data, legend pos=north east, ] \addplot table[x expr=\coordindex,y index=1] {\loadedtable}; \addplot table[x expr=\coordindex,y index=2] {\loadedtable}; \legend{male,female} \end{axis} \end{tikzpicture}

\end{document}

enter image description here


Note that some things are still hardcoded, namely the column headers in the table, the field names in the data rows, the number of categories (with associated y values) and the legend. The headers are actually not needed (the category column for the xticklabels can be referred by index as well), but this requires the header=false option to \pgfplotstableread which makes \expandafter more complicated. Looping the json array can probably be generalized within the Lua code but for this proof-of-concept answer I didn't look into that. Finally the separate \addplot table statements and the legend, this can be done using \foreach. See Use first row of a table as legend entry in pgfplot graph? for some examples of the remarks above.

Marijn
  • 37,699