我们想在 Latex 中制作下面的图表,但发现编写代码很困难。
当我们尝试在 var 中定义 fm 时,由于 fm 不是数字,因此无法编译。如果我们仅插入数字,则表格将正确生成。
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{tikzpicture}
\pgfplotstableread{
var Cat1 Cat2
fm 10 50
fc0 -40 60
ft0 -20 60
fvr 10 50
E0 -40 60
E90 -20 60
G0 10 50
G90 -40 60
CM -20 60
XR 10 50
GK1 -40 60
Gk2 -20 60
GK3 10 50
Qk -40 60
Wk -20 60
}\mytable
\begin{axis}[
xbar stacked,
% is default anyway:
stack negative=separate,
%
/pgf/number format/1000 sep=,
xmajorgrids,
nodes near coords,
nodes near coords style={font=\tiny},
ytick distance=1,
legend style={at={(0.5,-0.1)},
anchor=north,legend columns=-1},
extra x ticks={0},
extra x tick style={grid style={black},
xticklabel=\empty},
]
\addplot table [x index=1,y=var] {\mytable};
\addplot table [x index=2,y=var] {\mytable};
\legend{Cat1,Cat2}
\end{axis}
\end{tikzpicture}
\end{document}
答案1
好的,这是所有相关元素的草图,仅使用基本元素Tikz
。我故意省略了所有压缩代码的方法,使用\forach
循环等。这样做的目的是让它保持简单,并且足够容易调整和扩展,以便 Latex/Tikz 的初学者使用。
让我们看一下结果和代码的相关部分。你可能需要查阅手册或多或少是并行的。
开始
\documentclass[10pt,border=3mm,tikz]{standalone}
\usepackage{amsmath}% for the partial derivatives
- 自动加载 tikz
- 创建一个具有合适宽度和高度的 pdf
graphicx
稍后通过包将此pdf 包含\includegraphics
到你的论文中,这样它就会保持为矢量图像amsmath
\partial
只是为您的图例提供了很好的支持
布局和数据
只需将数据乘以 10 即可获得厘米,并将所有内容设置为绝对坐标(大多数情况下)。以下是如何绘制外框:
% ~~~ outer box ~~~~~~~~~~~~~~
\draw (-12,0) rectangle +(24,15);
- 从 (-12,0) (左下角)开始
- 在那里放一个矩形
- 使用相对坐标(
+
),即添加 24 厘米水平和 15 厘米垂直;您也可以计算绝对端点,但这更容易 - 你可能想改变它
line width
,例如thick
网格
非常相似,但 x 方向的步数增加了:
% ~~~ grid ~~~~~~~~~~~~~~
\draw[gray!50] (-12,0) grid[xstep=5] +(24,15);
数据条和样式
事实证明,最好在左边画一个矩形,在右边画另一个矩形。 y 值从下到上仅增加 1 厘米,其中 -9 厘米对应左侧数据的 0.9,.3 为矩形的高度:
\draw[dy] (0,14) rectangle +(-9,.3); \draw[py] (0,14) rectangle +( 4,.3);
这两个样式语句和所有其他语句都是在开头定义的:
\begin{tikzpicture}[% ~~~ self-defined styles ~~~~~
dy/.style={fill=brown!70},
py/.style={fill=brown!30},
lbl/.style={font={\Huge}},
ylbl/.style={lbl, anchor=east},% for y-axis, but I like lbl more (centered)
]
因此,您在此处应用的任何更改都适用于整个图表:
dy
,py
只需定义并应用填充颜色lbl
,ylbl
关注的是放置标签文本
我故意让数据条“在网格上游动”,因为太懒,所以可能创造了一些有趣的视觉效果。
x 标签
直截了当:
% ~~~ some x-labels ~~~~~~~~~~~~~
\node[lbl] at (-10,-1) {1};
\node[lbl] at (-5,-1) {0.5};
\node[lbl] at ( 10,-1) {1};
\node[lbl] at ( 5,-1) {0.5};
y 标签
类似地,旋转 y 方向的文本:
% ~~~ y-labels ~~~~~~~~~~~~~
\node[lbl] at (-13,14) {$f_{c,0}$};
\node[lbl] at (-13,6) {$X_R$};
\node[lbl] at (-13,3) {$G_{k3}$};
\node[lbl] at (-13,2) {$Q_k$};
\node[lbl] at (-13,1) {$W_k$};
\node[lbl,rotate=90] at (-15,6) {Stochastic variable X};
如果要将标签与其右边缘对齐,请使用ylbl
,将节点设置anchor point
为east
,即中间右侧。
如您所见,节点可以在内部保存任何 Latex 文本{ }
,例如使用数学模式的数学文本$ ... $
。
最后:传奇
也不是很令人兴奋:
% ~~~ legend ~~~~~~~~~~~~~~~~
\node[lbl] at (0,-2) {\%};
% partials
\draw[dy] (-5,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\mu}\ \frac{\mu}{\beta}$};
\draw[py] ( 2,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\sigma}\ \frac{\sigma}{\beta}$};
\draw
选择起点- 把 a
rectangle
当作正方形 - 在完成此路径(带有
;
)之前,放置另一个节点(带有文本) - 在极坐标中移动这个节点,
shift=(-35:1)
以便更好地定位数学 - 放入一些偏导数
- 请在
\
中间插入一个空格,从视觉上将两个分数分开 - 完成路径
;
完整代码:
\documentclass[10pt,border=3mm,tikz]{standalone}
\usepackage{amsmath}% for the partial derivatives
\begin{document}
\begin{tikzpicture}[% ~~~ self-defined styles ~~~~~
dy/.style={fill=brown!70},
py/.style={fill=brown!30},
lbl/.style={font={\Huge}},
ylbl/.style={lbl, anchor=east},% for y-axis, but I like lbl more (centered)
]
% ~~~ outer box ~~~~~~~~~~~~~~
\draw (-12,0) rectangle +(24,15);
% ~~~ grid ~~~~~~~~~~~~~~
\draw[gray!50] (-12,0) grid[xstep=5] +(24,15);
% ~~~ some bars ~~~~~~~~~
\draw[dy] (0,14) rectangle +(-9,.3); \draw[py] (0,14) rectangle +( 4,.3);
\draw[dy] (0, 7) rectangle +( 0,.3); \draw[py] (0, 7) rectangle +( 0,.3);
\draw[dy] (0, 6) rectangle +(-6,.3); \draw[py] (0, 6) rectangle +(.1,.3);
\draw[dy] (0, 1) rectangle +(-1,.3); \draw[py] (0, 1) rectangle +( 4,.3);
% ~~~ some x-labels ~~~~~~~~~~~~~
\node[lbl] at (-10,-1) {1};
\node[lbl] at (-5,-1) {0.5};
\node[lbl] at ( 10,-1) {1};
\node[lbl] at ( 5,-1) {0.5};
% ~~~ y-labels ~~~~~~~~~~~~~
\node[lbl] at (-13,14) {$f_{c,0}$};
\node[lbl] at (-13,6) {$X_R$};
\node[lbl] at (-13,3) {$G_{k3}$};
\node[lbl] at (-13,2) {$Q_k$};
\node[lbl] at (-13,1) {$W_k$};
\node[lbl,rotate=90] at (-15,6) {Stochastic variable X};
% ~~~ legend ~~~~~~~~~~~~~~~~
\node[lbl] at (0,-2) {\%};
% partials
\draw[dy] (-5,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\mu}\ \frac{\mu}{\beta}$};
\draw[py] ( 2,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\sigma}\ \frac{\sigma}{\beta}$};
\end{tikzpicture}
\end{document}
PS:让这段代码更紧凑、更通用
让我们介绍一些循环,像这样:
\foreach \x [count=\i] in {1, .2, .1, .2, .3, 6, 0,0, 1,0,1,0,0,9,0}
\draw[dy] (0, \i) rectangle +(-\x,.3);
- 它遍历给定的列表
{1, .2, ... 0}
- 将每个元素分配给
\x
每个循环 - 并将元素计数为
\i
(1、2、3、...) - 使用它们进行路径构造,例如在
\draw
或稍后的\node
\x
当然,数据是根据你的截图粗略估计的
% ~~~ making things more compact ~~~~~~~~~~~~~~~~~
\begin{tikzpicture}[% ~~~ self-defined styles ~~~~~
dy/.style={fill=brown!70,yshift=-1.5mm},% "centering" swimming bar
py/.style={fill=brown!30,yshift=-1.5mm},
lbl/.style={font={\Huge}},
ylbl/.style={lbl, anchor=east},% for y-axis, but I like lbl more (centered)
]
% ~~~ grid ~~~~~~~~~~~~~~
\draw[gray!50] (-12,0) grid[xstep=5] +(24,16);
% ~~~ outer box ~~~~~~~~~~~~~~
\draw[line width=5pt] (-12,0) rectangle +(24,16);
% ~~~ all bars ~~~~~~~~~~~~~~~~~~~~~~
\foreach \x [count=\i] in {1, .2, .1, .2, .3, 6, 0,0, 1,0,1,0,0,9,0}
\draw[dy] (0, \i) rectangle +(-\x,.3);
\foreach \x [count=\i] in {4,0,0,0,0,.3,0,0,.1,0,.09,0,0,4,0}
\draw[py] (0, \i) rectangle +(\x,.3);
% ~~~ some x-labels, saving lines ~~~~~~~~~~~~~
\node[lbl] at (-10,-1) {1} node[lbl] at (-5,-1) {0.5};
\node[lbl] at ( 10,-1) {1}; \node[lbl] at ( 5,-1) {0.5};
% ~~~ y-labels ~~~~~~~~~~~~~
\foreach \t [count=\i] in { W_k, Q_k, G_{k3}, G_{k2}, G_{k1}, X_R, C_M,
G_{90}, G_0, E_{90}, E_0, f_{v,r}, f_{t,0}, f_{c,0}, f_m }
\node[lbl] at (-13,\i) {$\t$};
\node[lbl,rotate=90] at (-15,6) {Stochastic variable X};
% ~~~ legend ~~~~~~~~~~~~~~~~
\node[lbl] at (0,-2) {\%};
% partials
\draw[dy] (-5,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\mu}\ \frac{\mu}{\beta}$};
\draw[py] ( 2,-4) rectangle +(1,1)
node[lbl,anchor=west,shift=(-35:1)]
{$\frac{\partial\beta}{\partial\sigma}\ \frac{\sigma}{\beta}$};
\end{tikzpicture}
答案2
另一种可能性是直接使用表中给出的数据。为了fm
不出现错误并正确对齐刻度,您必须添加三项内容:
\addplot table [x index=1,y expr=\coordindex] {\mytable};
,其中y expr=\coordindex
给出 y 坐标的对应值 (0, 1, 2 ... 14)。yticklabels from table={\mytable}{var},
因此 y 坐标获取表中的“文本值”。- 此时,您会看到一些内容,但
fm
缺少与第一个变量(即)对应的标签。要添加它,您必须y ticks
相应地定义。由于您有 15 个变量,因此您可以在轴中写入ytick={0,...,14},
编辑:并注意pgfplotstable
序言中的!
其结果(+X 轴和 Y 轴上的标签)如下。您可以看到它需要微调才能实现所需的图形,例如分离/减小不同条形的宽度并更改其颜色。
以及对应的代码:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepackage{pgfplotstable}
\begin{document}
\begin{tikzpicture}
\pgfplotstableread{
var Cat1 Cat2
fm 10 50
fc0 -40 60
ft0 -20 60
fvr 10 50
E0 -40 60
E90 -20 60
G0 10 50
G90 -40 60
CM -20 60
XR 10 50
GK1 -40 60
Gk2 -20 60
GK3 10 50
Qk -40 60
Wk -20 60
}\mytable
\begin{axis}[
xbar stacked,
% is default anyway:
stack negative=separate,
%
/pgf/number format/1000 sep=,
xmajorgrids,
nodes near coords,
nodes near coords style={font=\tiny},
ytick distance=1,
legend style={at={(0.5,-0.2)},
anchor=north,legend columns=-1},
extra x ticks={0},
extra x tick style={grid style={black},
xticklabel=\empty},
yticklabels from table={\mytable}{var}, % <- added code
ytick={0,...,14},% <- added code
xlabel = {\%},
ylabel = {Stochastic variable X},
bar width = 0.25cm, % Controls bar width
]
\addplot table [x index=1,y expr=\coordindex] {\mytable}; % <- added code
\addplot table [x index=2,y expr=\coordindex] {\mytable}; % <- added code
\legend{$\frac{\partial\beta}{\partial\mu}\ \frac{\mu}{\beta}$,$\frac{\partial\beta}{\partial\sigma}\ \frac{\sigma}{\beta}$}
\end{axis}
\end{tikzpicture}
\end{document}