堆积条形图、整个条形图的百分比和总值

堆积条形图、整个条形图的百分比和总值

我已经在想要达到的目标上取得了很大进展,但仍有一些需要改进的地方。我现在拥有的图像如下:

http://i.imgur.com/GwsEcvx.png

但是,我们可以看到,这些百分比都是相对于 Ref 的,Ref 为 100%。查看第二条(x 轴 4),我们有 64.2+1.6+20.6 = 86.4 != 100。除此之外,最好所有堆栈的总时间都显示在它上面。我的想法粗略概括如下:

在此处输入图片描述

文件数据.txt:

one,two,three,four
Ref,0.0,194.228732386,0.0
4,40.0069652252,3.1391023845,124.752030532
8,31.416268219,4.0078951455,111.883188346
9,76.8558069667,3.9906615645,112.515372569
11,82.992369082,4.38474317025,112.11896845
13,81.5133020117,4.27987078675,116.598416893
16,81.5851874813,8.44496483425,117.332427258

Latex 文件:

\pgfplotstableread[col sep = comma]{data.txt}\mydata

\makeatletter

% To allow the 'Ref' x-axis entry
\pgfplotsset{
    /pgfplots/flexible xticklabels from table/.code n args={3}{%
        \pgfplotstableread[#3]{#1}\coordinate@table
        \pgfplotstablegetcolumn{#2}\of{\coordinate@table}\to\pgfplots@xticklabels
        \let\pgfplots@xticklabel=\pgfplots@user@ticklabel@list@x
    }
}

% For calculating the percentage
\pgfplotsset{
    compat=1.5.1,
    percentage ticks/.code={
        \pgfplotsset{
            xtick pos=left,
            axis x line*=left,
            xlabel=Units,
            nodes near coords={
                \pgfkeys{
                    /pgf/fpu=true,  % PGFplots uses floating points internally
                    /pgf/fpu/output format=fixed
                }
                \pgfmathparse{100*\pgfplotspointmeta/\pgfplots@axiswide@metamax}
                \pgfmathprintnumber{\pgfmathresult}\,\%
            },
            every node near coord/.append style={yshift=1ex}
        }
    }
}
\makeatother


\begin{tikzpicture}
\begin{axis}[
/pgf/number format/precision=1,
compat=newest, %Better label placement
ybar stacked,
width=1.2\textwidth,
height=0.4\textheight,
enlarge y limits={upper, value=0.2},
ymin=0,
enlarge x limits = 0.2,
bar width=32pt,
title={Instance els19 with 1\% max error},
legend style={at={(0.5,-0.15)},
anchor=north,legend columns=0},
ylabel={Time in milisseconds},
xtick=data,
flexible xticklabels from table={data.txt}{one}{col sep=comma},
xticklabel style={text height=1.5ex},
nodes near coords,
axis lines*=left,
cycle list={
    {fill=black!30,draw=black!30},
    {fill=black!20,draw=black!20},
    {fill=black!10,draw=black!10}
},
axis on top,
major grid style=white,
ymajorgrids,
legend style={draw=none,/tikz/every even column/.append style={column sep=0.5cm}},
percentage ticks
]
\addplot table[x expr=\coordindex, y=two]{\mydata};
\addplot table[x expr=\coordindex, y=three]{\mydata};
\addplot table[x expr=\coordindex, y=four]{\mydata};
\legend{Best 1\%,Average 1\%,Worst 1\%}
\end{axis}
\end{tikzpicture}

我觉得最有趣的一行是:

\pgfmathparse{100*\pgfplotspointmeta/\pgfplots@axiswide@metamax}

但是,我查阅手册很长时间也无法找到适合“当前”栏的宏。

任何帮助/指点都将不胜感激!

答案1

由于人们对此表示赞同,我想我应该用我的解决方案来回应:

我用总和扩展了数据字段,这在我的例子中是可行的。我相信您也可以通过使用 \pgfplotstable 创建临时表来做到这一点。

% Showing the sum on top
\pgfplotsset{
        show sum on top/.style={
            /pgfplots/scatter/@post marker code/.append code={%
                \pgfkeys{
                    /pgf/fpu=true,  % PGFplots uses floating points internally
                    /pgf/fpu/output format=fixed
                }
                \pgfmathparse{\pgfkeysvalueof{/data point/x}}
                \pgfmathtruncatemacro\xidx{\pgfmathresult}
                \pgfplotstablegetelem{\xidx}{sum}\of{\mydata}
                \let\yval\pgfplotsretval
                \node[
                    at={(normalized axis cs:%
                            \pgfkeysvalueof{/data point/x},%
                            \yval)%
                    },
                    anchor=south,
                ]
                {
                    \pgfmathprintnumber{\yval}
                };
            },
        },
    }

\pgfplotsset{
    percentage ticks/.code={
        \pgfplotsset{
            nodes near coords={
                \pgfkeys{
                    /pgf/fpu=true,  % PGFplots uses floating points internally
                    /pgf/fpu/output format=fixed
                    %/pgf/number format/.cd,fixed,fixed zerofill, precision=2
                }
                \pgfmathparse{\pgfkeysvalueof{/data point/x}}
                \pgfmathtruncatemacro\xidx{\pgfmathresult}
                \pgfplotstablegetelem{\xidx}{sum}\of{\mydata}
                \pgfmathparse{100*\pgfplotspointmeta/\pgfplotsretval}
                \let\percent\pgfmathresult
                \ifthenelse{\lengthtest{\percent pt=100 pt}}{
                    \pgfmathprintnumber[fixed,fixed zerofill, precision=0]{\percent}\%
                }{
                    \ifthenelse{\lengthtest{\percent pt<10 pt}}{
                        \pgfmathprintnumber[fixed,fixed zerofill, precision=2]{\percent}\%
                    }{
                        \pgfmathprintnumber[fixed,fixed zerofill, precision=1]{\percent}\%
                    }
                }
            },
            every node near coord/.append style={yshift=1.2ex,xshift=-1.7ex,font=\footnotesize} %anchor=west,xshift=-7.2ex}
        }
    }
}

\begin{axis} [
    xtick=data,
    flexible xticklabels from table={data.txt}{gran}{col sep=comma},
    xticklabel style={text height=1.5ex},
    nodes near coords,
    percentage ticks
]
    \addplot table[x expr=\coordindex, y=two]{\mydata};
    \addplot [show sum on top] table[x expr=\coordindex, y=three]{\mydata}; % Note that "show sum on top" should be applied to the plot which always is different from 0
    \addplot table[x expr=\coordindex, y=four]{\mydata};
    \legend{Prefetch, Execute, Optimized}
\end{axis}

恐怕这不是一个非常简单的工作示例,但它展示了以下想法:

通过获取 x 索引来计算百分比,然后使用该索引在表中查找总和,然后将节点的 y 值除以总和。

在条形图顶部添加总和有点类似。对于每个 x 轴上的一个项目(我选择“two”图,因为该图始终具有非零值),您只需创建一个具有(x=x,y=总和值)坐标的节点。显然零值会被忽略,我不确定如何处理。同样值得注意的是,我只修改了片段,因为它们最初来自 tex SE 上的其他线程。

相关内容