我正在使用这个代码并且它运行良好:如何使用 pgfplots 绘制漂亮的人口金字塔图?
答案1
我改编了您在问题中提供的链接中的代码以得到期望的结果。
因为只有 x 值有刻度线,所以需要绘制三个轴:一个用于“男人”数据,一个用于“女人”数据,一个仅用于绘制 y 数据,因为无法tick length
独立设置 x 轴和 y 轴。
有关更多详细信息,请查看代码中的注释。
% 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}