如何使用 pgfplots 绘制漂亮的人口金字塔图?

如何使用 pgfplots 绘制漂亮的人口金字塔图?

我正在尝试绘制人口金字塔图形。

我写了这个 MWE。

\documentclass{article}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{document}
\pgfplotstableread[col sep=comma]{
age,man,woman
+100 years,0,4
95 - 99 years,3,6
90 - 94 years,10,16
85 - 89 years,43,57
80 - 84 years,103,111
75 - 79 years,175,224
70 - 74 years,274,322
65 - 69 years,421,427
60 - 64 years,514,524
55 - 59 years,578,606
50 - 54 years,732,785
45 - 49 years,885,911
40 - 44 years,1044,1120
35 - 39 years,1192,1289
30 - 34 years,1315,1306
25 - 29 years,1214,1362
20 - 24 years,1360,1336
15 - 19 years,1471,1406
10 - 14 years,1495,1446
5 - 9 years,1375,1351
0 - 4 years,1325,1257
}\loadedtable


\begin{tikzpicture}
\begin{axis}[
    width =\textwidth,
    height = 0.6*\textheight,
    enlarge x limits=0.6,
    xbar = 0pt,
    xmin = -5,
    xmax = 5,
    y dir = reverse,
    nodes near coords,
    bar width=8pt,
    bar shift=0pt,
    axis x line= left,
    nodes near coords = {\pgfmathprintnumber\pgfplotspointmeta\%},
    every node near coord/.append style={font=\scriptsize, color=black},
    xticklabel= {\pgfmathprintnumber\tick\%},
    symbolic y coords={+100 years,95 - 99 years,90 - 94 years,85 - 89 years,80 - 84 years,75 - 79 years,70 - 74 years,65 - 69 years,60 - 64 years,55 - 59 years,50 - 54 years,45 - 49 years,40 - 44 years,35 - 39 years,30 - 34 years,25 - 29 years,20 - 24 years,15 - 19 years,10 - 14 years,5 - 9 years,0 - 4 years},
   ytick={+100 years,95 - 99 years,90 - 94 years,85 - 89 years,80 - 84 years,75 - 79 years,70 - 74 years,65 - 69 years,60 - 64 years,55 - 59 years,50 - 54 years,45 - 49 years,40 - 44 years,35 - 39 years,30 - 34 years,25 - 29 years,20 - 24 years,15 - 19 years,10 - 14 years,5 - 9 years,0 - 4 years}
            ]
        \addplot [fill = cyan!50]    table[y=age,x expr={-\thisrow{man}/31395*100}] \loadedtable;%31395 is the total population
        \addlegendentry{Man}
        \addplot [fill = magenta!50] table[y=age,x expr={\thisrow{woman}/31395*100}] \loadedtable;%31395 is the total population
        \addlegendentry{Woman}
    \end{axis}
\end{tikzpicture}
\end{document}

但结果却是一张丑陋的图表:

在此处输入图片描述

我怎样才能改进它以获得这样的效果?

在此处输入图片描述

答案1

想要漂亮需要付出很多努力!

\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\usepackage{pgfplotstable}
\usepackage{wasysym}

\begin{document}
\pgfplotstableread[col sep=comma]{
age,man,woman
+100 years,0,4
95 - 99 years,3,6
90 - 94 years,10,16
85 - 89 years,43,57
80 - 84 years,103,111
75 - 79 years,175,224
70 - 74 years,274,322
65 - 69 years,421,427
60 - 64 years,514,524
55 - 59 years,578,606
50 - 54 years,732,785
45 - 49 years,885,911
40 - 44 years,1044,1120
35 - 39 years,1192,1289
30 - 34 years,1315,1306
25 - 29 years,1214,1362
20 - 24 years,1360,1336
15 - 19 years,1471,1406
10 - 14 years,1495,1446
5 - 9 years,1375,1351
0 - 4 years,1325,1257
}\loadedtable

\newlength{\dy}\setlength{\dy}{\baselineskip}
\newlength{\dx}\setlength{\dx}{0.007em}
\newlength{\temp}

\pgfplotstablegetrowsof{\loadedtable}
\pgfmathparse{\pgfplotsretval-1}
\edef\rows{\pgfmathresult}
% compute total for percentages
\setlength{\temp}{0pt}
\foreach \y in {0,1,...,\rows}{%
  \pgfplotstablegetelem{\y}{man}\of\loadedtable
  \global\advance\temp by \pgfplotsretval pt
  \pgfplotstablegetelem{\y}{woman}\of\loadedtable
  \global\advance\temp by \pgfplotsretval pt
}
\pgfmathparse{0.01\temp}
\edef\total{\pgfmathresult}

\noindent\begin{tikzpicture}

\node at (0,2\dy) {Population Pyramid - 2010};
\node[below,text=Navy] at (-8em,0) {\huge\mars};
\node[below,text=HotPink] at (8em,0) {\huge\venus};

\foreach \y in {0,1,...,\rows}{%
  \pgfplotstablegetelem{\y}{age}\of\loadedtable
  \node[left] at (-19em,-\y\dy) {\strut\pgfplotsretval};
  \pgfplotstablegetelem{\y}{man}\of\loadedtable
  \node[left] at (-15em,-\y\dy) {\strut\pgfplotsretval};
  \node[left,fill=Navy,text width=\pgfplotsretval\dx,text height=.8\dy,inner sep=0]
    at (0,-\y\dy+0.1\dy) {};
  \pgfmathparse{\pgfplotsretval/\total}
  \pgfmathprintnumberto[fixed,precision=2]{\pgfmathresult}{\per}
  \node[left] at (-\pgfplotsretval\dx,-\y\dy) {\small\strut\per\%};
  \pgfplotstablegetelem{\y}{woman}\of\loadedtable
  \node[left] at (17em,-\y\dy) {\strut\pgfplotsretval};
  \node[right,fill=HotPink,text width=\pgfplotsretval\dx,text height=.8\dy,inner sep=0]
    at (0,-\y\dy+0.1\dy) {};
  \pgfmathparse{\pgfplotsretval/\total}
  \pgfmathprintnumberto[fixed,precision=2]{\pgfmathresult}{\per}
  \node[right] at (\pgfplotsretval\dx,-\y\dy) {\small\strut\per\%};
}
\node[left] at (-3em,-\rows\dy-.9\dy) {Man};
\node[left,fill=Navy,text width=2em,text height=.8\dy,inner sep=0]
  at (-1mm,-\rows\dy-.9\dy) {};
\node[right,fill=HotPink,text width=2em,text height=.8\dy,inner sep=0]
  at (+1mm,-\rows\dy-.9\dy) {};
\node[right] at (3em,-\rows\dy-.9\dy) {Woman};

\end{tikzpicture}
\end{document}

金字塔

您可以通过调整字体来调整大小,或者使用 \resizebox 来更精确地调整大小。

答案2

这个看起来好多了 = )

\documentclass[10pt]{article}
\usepackage{pgfplots}\pgfplotsset{compat=1.10}
\usepackage{pgfplotstable}
\usepackage{lmodern}
\usepackage{wasysym}
\begin{document}

\pgfplotstableread[col sep=comma, header=true]{
age,man,woman
+100 years,0,4
95 - 99 years,3,6
90 - 94 years,10,16
85 - 89 years,43,57
80 - 84 years,103,111
75 - 79 years,175,224
70 - 74 years,274,322
65 - 69 years,421,427
60 - 64 years,514,524
55 - 59 years,578,606
50 - 54 years,732,785
45 - 49 years,885,911
40 - 44 years,1044,1120
35 - 39 years,1192,1289
30 - 34 years,1315,1306
25 - 29 years,1214,1362
20 - 24 years,1360,1336
15 - 19 years,1471,1406
10 - 14 years,1495,1446
5 - 9 years,1375,1351
0 - 4 years,1325,1257
}\loadedtable

\begin{tikzpicture}
\begin{axis}[
    name=popaxis,
    scale only axis,
    xbar,
    xmin=0,
    xmax=5,
    %xbar=2pt,
    %xlabel={\%},
    width=0.5*\textwidth, height= 0.5*\textheight,
   y dir = reverse,
   nodes near coords = {\pgfmathprintnumber\pgfplotspointmeta\%},
   every node near coord/.append style={font=\scriptsize, color=black},
   xticklabel= {\pgfmathprintnumber\tick\%},
    y tick label style={text width=3cm,align=center},
    axis x line=left,
    axis y line=none,
%
    enlarge x limits = {value=0.15,upper},
    axis line style={-},
    clip=false
]
\addplot[magenta,fill=magenta!50] table[y expr =\coordindex, x expr={\thisrow{woman}/31395*100}] \loadedtable;%total pop = 31395 
%
\pgfplotstablegetrowsof{\loadedtable}
\pgfmathsetmacro{\lastrow}{\pgfplotsretval-1}  
\node[xshift=-1.5cm,yshift=-0.5cm,align=center] at (axis cs:0,\lastrow) {\textcolor{cyan}{\huge\mars} Man}; 
\node[xshift= 1.5cm,yshift=-0.5cm,align=center] at (axis cs:0,\lastrow) {\textcolor{magenta}{\huge\venus} Woman}; 
\node[xshift= 0.0cm,yshift=-2.0cm,align=center] at (axis cs:0,\lastrow) {\%}; 
%
\end{axis}
\begin{axis}[ 
at={(popaxis.north west)},anchor=north east, %xshift=-3cm,
scale only axis,
    xbar = 0,
    xmin = 0,
    xmax = 5,
    width=0.5*\textwidth,
    height= 0.5*\textheight,
    x dir=reverse,
    y dir=reverse,
    nodes near coords = {\pgfmathprintnumber\pgfplotspointmeta\%},
    every node near coord/.append style={rotate = 0, anchor = east, font=\scriptsize, color=black},
    xticklabel= {\pgfmathprintnumber\tick\%},
    axis x line=left,
    axis y line*=left,
%
    ytick = data,
    yticklabels from table = {\loadedtable}{age},
    ytick align=center,
    ytick pos=left,
    enlarge x limits = {value=0.15,upper},
    axis line style={-}
]
\addplot[cyan,fill=cyan!50] table[y expr =\coordindex, x expr={\thisrow{man}/31395*100}] \loadedtable; %total pop = 31395 
\end{axis}
\end{tikzpicture}
\end{document}

更漂亮

相关内容