我有一张.csv
包含分类数据和数字数据的表。
- 第一列包含类别,以字符串表示。
- 第二列包含属于每个类别的观测值数量。这是表中唯一的数字数据。
- 其余列包含每个观察的各种出现情况,这些出现情况是字符串。
直观地了解文件的结构:
CATEGORIES NOBS OCCURRENCE1 OCCURRENCE2 OCCURRENCE3
Street 3 Street A Street XXXXX Street YY
Square 2 Square ZZZZ Square B ''
Lane 1 Lane XXXXX '' ''
Park 1 Park A '' ''
注意,有些字符串可能为空。此外,字符串的长度是可变的。
从这些数据开始,我希望获得如下所示的数字。
理想情况下,我有兴趣总体长度每行一致NOBS。这可能需要减小某些行的字体大小,如果需要,我准备手动执行此操作。但是,必须确定各个框的宽度,以便生成与 NOBS 一致的条形图的整体大小。另一种方法是使用宽度等于最长字符串的固定文本框大小:这样,每个条形图的整体长度在构造上将与 NOBS 一致。
我曾尝试研究如何实现这种类型的图形,但迄今为止失败了。我是否完全错过了一些软件包或其他有用的解决方案?任何帮助都将不胜感激。
答案1
这是朝着正确的方向发展的吗?
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{datatable.csv}
CATEGORIES;NOBS;OCCURRENCE1;OCCURRENCE2;OCCURRENCE3
Street;3;Street A;Street XXXXX;Street YY
Square;2;Square ZZZZ;Square B;''
Lane;1;Lane XXXXX;'';''
Park;1;Park A;'';''
\end{filecontents*}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.16}
\newcounter{realitems}
\begin{document}
\begin{tikzpicture}[font=\sffamily,header/.style={text
width=2.4cm,align=left,fill=gray!20,minimum height=8mm,draw,inner xsep=1ex},
funky bar/.cd,inner sep/.initial=1ex,width/.initial=2.1cm]
% your empty cell indicator
\edef\none{''}
% load table and figure out how many rows and columns it has
\pgfplotstableread[col sep=semicolon]{datatable.csv}\loadedtable
\pgfplotstablegetrowsof{\loadedtable}
\pgfmathtruncatemacro{\NumRows}{\pgfplotsretval-1}
\pgfplotstablegetcolsof{\loadedtable}
\pgfmathtruncatemacro{\NumCols}{\pgfplotsretval-1}
% loop
\foreach \Row in {0,...,\NumRows}
{\setcounter{realitems}{0} %measure the items
\foreach \Col in {2,...,\NumCols}
{\pgfplotstablegetelem{\Row}{[index]\Col}\of{\loadedtable}
\ifx\pgfplotsretval\none
\else
\stepcounter{realitems}
\ifnum\number\value{realitems}=1
\xdef\CurLst{"\pgfplotsretval"}
\pgfmathsetmacro{\tmpwd}{width("\pgfplotsretval")}
\xdef\tmpwd{\tmpwd}
\else
\xdef\CurLst{\CurLst,"\pgfplotsretval"}
\pgfmathsetmacro{\tmpwd}{\tmpwd+width("\pgfplotsretval")}
\xdef\tmpwd{\tmpwd}
\fi
\fi
}
\typeout{\Row,\CurLst}
\pgfmathsetmacro{\ratio}{\number\value{realitems}*
(\pgfkeysvalueof{/tikz/funky bar/width}-2*\pgfkeysvalueof{/tikz/funky bar/inner sep})/\tmpwd}
\pgfplotstablegetelem{\Row}{[index]0}\of{\loadedtable}
\ifnum\Row=0
\node[header,alias=n-\Row-0] (H\Row) {\pgfplotsretval};
\else
\node[header,alias=n-\Row-0,below=-\pgflinewidth\space of H\the\numexpr\Row-1] (H\Row) {\pgfplotsretval};
\fi
\foreach \X [evaluate=\X as \PrevX using {int(\X-1)}] in {1,...,\number\value{realitems}}
{\ifnum\number\value{realitems}=1
\pgfmathsetmacro{\myitem}{\CurLst}
\typeout{\myitem}
\pgfmathsetmacro{\mywidth}{\pgfkeysvalueof{/tikz/funky bar/width}}
\node[anchor=center,inner sep=0pt,scale=\ratio] (n-\Row-\X)
at ([xshift=\mywidth/2]n-\Row-\PrevX.east) {\myitem};
\draw ([yshift=-\pgflinewidth/2]n-\Row-0.north -| n-\Row-\PrevX.east)
-- ++ (\mywidth pt,0) |- ([yshift=\pgflinewidth/2]n-\Row-0.south -| n-\Row-\PrevX.east);;
\else
\pgfmathsetmacro{\myitem}{{\CurLst}[\X-1]}
\pgfmathsetmacro{\mywidth}{2*\pgfkeysvalueof{/tikz/funky bar/inner sep}+\ratio*width("\myitem")}
\node[anchor=center,inner sep=0pt,scale=\ratio,
right={ifthenelse(\X==1,1,2)*\pgfkeysvalueof{/tikz/funky bar/inner sep}}
of n-\Row-\PrevX] (n-\Row-\X) {\myitem};
\draw ([yshift=-\pgflinewidth/2]n-\Row-0.north -| n-\Row-\PrevX.east)
-- ++ (\mywidth pt,0) |- ([yshift=\pgflinewidth/2]n-\Row-0.south -| n-\Row-\PrevX.east);;
\fi
}
}
\end{tikzpicture}
\end{document}