我有一个类似这样的 JSON 文件
{
"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
}
]
}
我需要创建一个带有动态 x 字段的条形图,这些字段是从 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}
谢谢..
答案1
合并如何绘制 JSON 数据和x 坐标中的逗号(间隔)给出下面的 MWE。
这个想法是使用tex.sprint
正确的格式将表写入输入流,就好像表数据实际写入文件中一样.tex
。然后\pgfplotstableread
可以一次读取整个表。
对于绘图,这需要选项xticklabels from table
和xtick=data
。每个类别都有一个单独的\addplot
命令,并y
在表中有相应的索引。
\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}
请注意,有些内容仍是硬编码的,即表中的列标题、数据行中的字段名称、类别数(带有关联y
值)和图例。标题实际上不是必需的(的类别列xticklabels
也可以通过索引引用),但这需要选项,header=false
这\pgfplotstableread
会使情况\expandafter
更加复杂。循环 json 数组可能可以在 Lua 代码中推广,但对于这个概念验证答案,我没有研究这一点。最后是单独的语句\addplot table
和图例,可以使用来完成\foreach
。参见使用表格的第一行作为 pgfplot 图中的图例条目?有关上述评论的一些例子。