1

I'm using this code and it works fine: How can I draw a pretty population pyramid graph with pgfplots?

But I want to draw the population pyramid like this in figure. Please guide me how to di it. enter image description here

  • 1
    Could you provide some code with what you have achieved so far by altering the code in the link? – Stefan Pinnow Mar 1 '16 at 6:28
5

I adapted the code from the link you provided in the question to give the desired result.

Because only the x values have tick lines it is needed to draw three axis: One for the "man" data, one for the "woman" data and one only for plotting the ydata, because the tick length cannot be set independently for the x and y axis.

For more details have a look at the comments in the code.

% done with pgfplots v1.13
\documentclass[10pt]{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{
        compat=1.9,
        %
        % create a style which is used for all the axis
        % this one is especially for drawing the axis plotting the y axis
        blank pyramid axis style/.style={
            width=0.5*\textwidth,
            height=0.5*\textheight,
            scale only axis,
            %
            xmin=0,
            xmax=5.5,
            ymin=-0.5,
            ymax=20,
            y dir=reverse,
            enlarge y limits={value=0.075,upper},
            %
            xbar,
            axis x line=left,
            xtick align=outside,
            %
            bar width=1,
            allow reversal of rel axis cs=false,
        },
        % this style is for the axis drawing the data
        pyramid axis style/.style={
            blank pyramid axis style,
            %
            % draw `xtick's as percent values
            xticklabel={%
                \pgfmathprintnumber\tick\%%
            },
            % don't draw any `ytick' values
            ytick=\empty,
%            % for debugging purposes draw draw data from loaded table as `ytick's
%            ytick=data,
%            yticklabels from table={\loadedtable}{age},
%            y tick label style={
%                major tick length=0pt,
%                align=center,
%                text width=12.5mm,
%                inner sep=0pt,
%                draw=red,
%                text=red,
%            },
            % just draw a line as axis lines
            axis line style={-},
            %
            % draw `nodes near coords' also in percentages
            nodes near coords={%
                \pgfmathprintnumber\pgfplotspointmeta\%%
            },
            % set the style of `nodes near coords'
            every node near coord/.append style={
                font=\scriptsize,
                color=black,
                /pgf/number format/fixed,
            },
        },
    }
\begin{document}
    \begin{tikzpicture}
        \pgfplotstableread[
            col sep=comma,
            header=true,
        ]{
            age,man,woman
            +100,0,4
            95--99,3,6
            90--94,10,16
            85--89,43,57
            80--84,103,111
            75--79,175,224
            70--74,274,322
            65--69,421,427
            60--64,514,524
            55--59,578,606
            50--54,732,785
            45--49,885,911
            40--44,1044,1120
            35--39,1192,1289
            30--34,1315,1306
            25--29,1214,1362
            20--24,1360,1336
            15--19,1471,1406
            10--14,1495,1446
            5--9,1375,1351
            0--4,1325,1257
        }\loadedtable
        % add a column in the table summing up the «man» and «woman» values
        % accumulatively
        % with the sum of all values one can calculate the percentages of the
        % values
        \pgfplotstablecreatecol[
            expr accum={
                round(\pgfmathaccuma) + \thisrow{man} + \thisrow{woman}
            }{0}
        ]{sum}{\loadedtable}
        % turn on `fpu' library when numbers are larger than 16384
        \tikzset{
            fpu=true,
        }
            % get the number of data rows of the loaded table
            \pgfplotstablegetrowsof{\loadedtable}
                \pgfmathsetmacro{\LastRow}{\pgfplotsretval-1}
            % now get the last entry of the «sum» column which contains the
            % sum of all «man» and «woman» values
            % (for whatever reason this doesn't seem to work; it is returned
            %  the value of the second row ...)
%            \pgfplotstablegetelem{\LastRow}{sum}\of{\loadedtable}
            \pgfplotstablegetelem{20}{sum}\of{\loadedtable}
                \pgfmathsetmacro{\Sum}{\pgfplotsretval}
        \tikzset{
            fpu=false,
        }
    % draw woman data on the «right» axis
        \begin{axis}[
            pyramid axis style,
            %
            % add here the additional key-values which are unique to this axis
            axis y line*=left,
            ytick=\empty,
            name=popaxis,
        ]
            \addplot [magenta,fill=magenta!50] table [
                y expr =\coordindex,x expr={\thisrow{woman}/\Sum*100},
            ] \loadedtable;

            \node [anchor=south] at (rel axis cs:0.25,1)
                {\textcolor{magenta}{Woman}};
        \end{axis}

    % draw man data on the «left» axis
        \begin{axis}[
            pyramid axis style,
            %
            % where should this axis be plotted
            at={(popaxis.west)},
            anchor=east,
            % shift to the left
            xshift=-12.5mm,
            %
            % add here the additional key-values which are unique to this axis
            x dir=reverse,
            every node near coord/.append style={
                anchor=east,
            },
            axis y line*=right,
        ]
            \addplot [cyan,fill=cyan!50] table [
                y expr =\coordindex, x expr={\thisrow{man}/\Sum*100},
            ] \loadedtable;

            \node [anchor=south] at (rel axis cs:0.25,1)
                {\textcolor{cyan}{Man}};
        \end{axis}

    % «dummy» axis to draw the y values
    % (the extra axis is needed because it seems that the tick length cannot
    %  be set independently for the x and y axis)
        \begin{axis}[
            blank pyramid axis style,
            %
            % where should this axis be plotted
            at={(popaxis.west)},
            anchor=east,
            xshift=-12.5mm,
            %
            % add here the additional key-values which are unique to this axis
            x dir=reverse,
            axis y line*=right,
            % don't draw `xtick's (they are already drawn with ticks)
            xtick=\empty,
            % draw `ytick's with the data from the table
            ytick=data,
            yticklabels from table={\loadedtable}{age},
            % set the style of `yticklabels'
            % (the labels should be plot centered between the axis;
            %  therefore use `align=center' and set the `text width'
            % so that
            y tick label style={
                align=center,
                inner sep=0pt,
                text width=12.5mm,
            },
            % set ticks length to zero
            major tick length=0pt,
            % make axis lines invisible
            axis line style={
                -,
                draw=none,
            },
        ]
            % add a dummy plot so that the axis ticks are drawn correctly
            \addplot [draw=none,fill=none] table [
                y expr =\coordindex, x expr={0},
            ] \loadedtable;

%            % dummy nodes to check the values of `\Sum' and `\LastRow'
%            \node [anchor=south] at (rel axis cs:0.5,1) {\pgfmathprintnumber{\Sum}};
%            \node [anchor=south] at (rel axis cs:0.75,1) {\pgfmathprintnumber{\LastRow}};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.