如何制作一个 pgfplots 堆叠 xbar 图,其中 bar-“显式元”标签根据输入表数据计算得出

如何制作一个 pgfplots 堆叠 xbar 图,其中 bar-“显式元”标签根据输入表数据计算得出

我正在制作一个 pgfplots 堆叠 xbar 图,其中每个条形除了数字条形长度外,还有一个不同的标签。每对条形还有一个共同的标签。我想用其不同的标签和长度标记每个条形,并用它们的共同标签标记每对条形。

我的问题分为两个部分(编辑:(1)已回答3):

  1. 如何避免定义额外的Score-name列(参见下面的 MWE),而是从表中的ScoreName 列计算它?编辑:根据包作者(回答3),没有内置对此的支持,但它在他的 TODO 列表中。编辑 2013-3-25:根据回答如下,现在已支持此功能。

  2. 如何使计算的标签出现在右侧 y 轴上,而不是在条形的末尾?

我不知道描述数据的最佳方式,但是每条 extra y tick标签,就像杰克对另一个问题可能会很好。

我不知道该怎么做每条 extra y tick标签,但我有替代解决方案,其中标签位置不太好:在输入数据表中添加一个额外的列并将其用于每个条形标签。此解决方案的问题包括:必须添加额外的列;无法使用 pgfplots 命令从额外的列格式化标签的数字部分(如下图所示);并且(主观上)它看起来不如extra u tick标签好看。

我的 MWE(也基于 Jake 对另一个问题。谢谢杰克!)有两张图。第一张图显示了我通过手动添加 Score-name列得到的解决方案,第二张图显示了第一张图中数字格式指令(即科学记数法)没有得到遵守(这看起来很自然,因为Score-name不是数字)。

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

\begin{filecontents}{data1.dat}
Age-interval  Y-Position  Score   Name  Score-name
20-30         1           0.15    Peter {0.15 (Peter)}
30-40         2           0.20    Jeff  {0.20 (Jeff)}
40-50         3           0.12    Steve {0.12 (Steve)}
50-60         4           1.24    John  {0.24 (John)}
\end{filecontents}

\begin{filecontents}{data2.dat}
Age-interval  Y-Position  Score    Name    Score-name
20-30         1           0.159    Peeteer {0.159 (Peeteer)}
30-40         2           0.209    Jeeff   {0.209 (Jeeff)}
40-50         3           0.129    Steevee {0.129 (Steevee)}
50-60         4           1.249    Joohn   {0.249 (Joohn)}
\end{filecontents}


\begin{document}

\begin{tikzpicture}
\begin{axis}[
    xlabel={The \texttt{format/sci} is ignored below, but the \texttt{font=\textbackslash{}small} is obeyed below:},
    xbar,     
    %bar width=2pt,
    ytick=data,
    width=8 cm,
    height=6 cm,
    enlarge y limits={true, value=0.2},
    xmin=-0.01,
    xmax = 2.0,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    %ylabel={Age intervals (yr)},
    nodes near coords,
    every node near coord/.append style={
      anchor=west,
      font=\small,
      % This format/sci gets ignored, because the Score-name is not a
      % number:
      /pgf/number format/sci,
      %/pgf/number format/zerofill,
      /pgf/number format/precision=2,
    },
    point meta=explicit symbolic
]
\addplot table [
    y=Y-Position,
    x=Score,
    meta=Score-name
] {data1.dat};
\addplot table [
    y=Y-Position,
    x=Score,
    meta=Score-name
] {data2.dat};

\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
    xlabel={Both the \texttt{format/sci} and the \texttt{font=\textbackslash{}small} are obeyed below:},
    xbar,     
    %bar width=2pt,
    ytick=data,
    width=8 cm,
    height=6 cm,
    enlarge y limits={true, value=0.2},
    xmin=-0.01,
    xmax = 2.0,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    %ylabel={Age intervals (yr)},
    nodes near coords,
    every node near coord/.append style={
      anchor=west,
      font=\small,
      % This format/sci gets ignored, because the Score-name is not a
      % number:
      /pgf/number format/sci,
      %/pgf/number format/zerofill,
      /pgf/number format/precision=2,
    },
    % THIS IS UNCOMMENTED ABOVE
    %point meta=explicit symbolic
]
\addplot table [
    y=Y-Position,
    x=Score,
    meta=Score-name
] {data1.dat};
\addplot table [
    y=Y-Position,
    x=Score,
    meta=Score-name
] {data2.dat};

\end{axis}
\end{tikzpicture}


\end{document}

我的解决方案 问题说明

答案1

这是一个自定义 hack,专门针对当前问题。首先,我们nodes near coords*根据自己的目的重新定义并删除许多必要的检查。因为我们确定我们不会使用它们。您必须将其置于 TikZ 图片环境中才能使其成为图片本地,否则所有图片都会受到影响。

然后,当将节点放置在坐标附近时,我们用(O)此处命名的坐标固定局部范围的边界框。然后我们在局部重置该范围内的变换。这使我们能够计算到右轴的距离y,并将west节点稍微向左移动。

关于第一个问题,您可以使用visualization depends on=键从其他表中收集数据,格式化数字打印等。

可能有更简单的定位方法,但我只是在自动驾驶仪上做到了。请使用它来展示更智能的方法。

完整代码如下:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=1.7}
\usetikzlibrary{calc}

\begin{filecontents}{data1.dat}
Age-interval  Y-Position  Score   Name  
20-30         1           0.15    Peter
30-40         2           0.20    Jeff  
40-50         3           0.12    Steve
50-60         4           1.24    John  
\end{filecontents}
\begin{filecontents}{data2.dat}
Age-interval  Y-Position  Score    Name    
20-30         1           0.159    Peeteer 
30-40         2           0.209    Jeeff   
40-50         3           0.129    Steevee 
50-60         4           1.249    Joohn   
\end{filecontents}

\pgfkeys{/pgfplots/nodes near coords*/.append style={scatter/@post marker code/.code={%
       \begin{scope}
         \coordinate (O) at (0,0);
         \pgftransformreset
         \path let \p1 = ($(axis description cs:1,1)-(O)$) in
          node[/pgfplots/every node near coord,anchor=west] at ([xshift=\x1+1.5mm]O) {#1};
       \end{scope}
       }
    }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    xbar,clip=false,     
    ytick=data,
    width=8 cm,height=6 cm,
    enlarge y limits={true, value=0.2},
    xmin=-0.01,xmax = 2.0,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data2.dat}{Age-interval},
    visualization depends on={value \thisrow{Name} \as \labela},
    visualization depends on={value \thisrow{Score} \as \labelb},
    every node near coord/.append style={
      font=\small,
    },
    nodes near coords={\pgfmathprintnumber[sci]{\labelb} (\labela)},
]
\addplot table [
    y=Y-Position,
    x=Score,
] {data1.dat};
\addplot table [
    y=Y-Position,
    x=Score,
] {data2.dat};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容