我正在尝试从一个表制作动画,该表包含每个帧(年份)的一行,其中行是一个解压缩的 9x7 矩阵:
Date, Row1Col1, Row1Col2, ..., Row9Col7
1864, 0.65, 0.01, ..., 0.2
我想将每一帧呈现为 2D 表面图。感谢:使用 pgfplots,如何排列数据矩阵以绘制曲面图,以便矩阵中的每个单元格都绘制为正方形?和使用 PGFPlots 构建二维直方图 我有这个作为一个最小示例的工作:
\documentclass{article}
\usepackage{fullpage}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\begin{document}
%For a 3x2 matrix output, need 4x3 input..., with a mesh/rows=4 OR a mesh/cols=3
\pgfplotstableread{
%x y value
0 0 0.5
0 1 4
%Dummy row
0 2 0
%
1 0 0
1 1 3
%dummy row
1 2 0
%
2 0 1
2 1 2
%dummy row
2 2 0
%
%Dummy column
3 0 4
3 1 4
%dummy row
3 2 0
%%
}\data
\begin{tikzpicture}
\begin{axis}[
view={0}{90},
colorbar,
xtick=data,
xticklabels={NotGuilty,Corporal,Death,},
x tick label style={anchor=north,yshift=0cm,xshift=1.3cm},
ytick=data,
y tick label style={anchor=east,yshift=1.3cm,xshift=0cm},
yticklabels={BreakingPeace,Damage,}
]
\addplot3[
surf,
shader=flat corner,
mesh/rows=4,
mesh/cols=3,
mesh/ordering=rowwise,
] table {\data};
\end{axis}
\end{tikzpicture}
\end{document}
现在我希望能够使用的方法是,我可以使用mesh/cols
并mesh/rows
在一行中解压数据,如下所示:
\pgfplotstableread{0 0 0.5 0 1 4 0 2 0 1 0 0 1 1 3 1 2 0 2 0 1 2 1 2 2 2 0 3 0 4 3 1 4 3 2 0 }\data
我可以获得一行来处理:
\pgfplotsset{table/col sep = comma,table/row sep=\\}
\pgfplotstableread{0,0,0.5\\0,1,4\\0,2,0\\1,0,0\\1,1,3\\1,2,0\\2,0,1\\2,1,2\\2,2,0\\3,0,4\\3,1,4\\3,2,0\\}\data
这种数据格式对于从我的原始数据中获取数据来说相当简单,但我需要它处理 200 行左右的数据,并希望我可以使用类似如下的方式循环遍历它们:
\foreach \row in {0,...200}{
...
\addplot[...] table[row = \row] \data
}
但是.. 没有这样的密钥!能否使用 pgf 技巧以某种方式将我的 CSV 动态转换为所需的行类型?
我试图避免将行转回矩阵,因为我可能需要为 pandas 中的每一行(约 300 行)生成一个新文件
另外,如何将标签动态移动到框的中心。如果它们位于位置 0.5、1.5 等,那么就可以了...
答案1
我已经找到了一种方法来做到这一点,它有点蛮力,并且需要额外的步骤来替换所有换行符以\\
将多行输出组合成一个长行:
sed ':a;N;$!ba;s/\n/\\\\/g'
当我整理好所有内容后,我将编辑帖子,其中包含使用 python pandas 准备数据的步骤。但 pgfplots 位至少在虚拟数据上起作用。我使用 sed 命令将所有行合并为一个长行,如上所述,用作\\
行分隔符,然后使用循环遍历列块范围,
select coords between index
感谢来自的 @Fritz如何从表中过滤/选择数据并绘制它?我们的一长行实际上是一整堆行(动画内容留在那里,因为这是最终的预期输出)
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\begin{document}
%Style to select only points from #1 to #2 (inclusive)
\pgfplotsset{select coords between index/.style 2 args={
x filter/.code={
\ifnum\coordindex<#1\def\pgfmathresult{}\fi
\ifnum\coordindex>#2\def\pgfmathresult{}\fi
}
}}
\newcommand{\rowlength}{12}
%For a 3x2 matrix output, need 4x3 input..., with a mesh/rows=4 OR a mesh/cols=3
\pgfplotsset{table/col sep = comma,table/row sep=\\}
\pgfplotstableread{%
0,0,0.1\\0,1,1.0\\0,2,0\\1,0,0\\1,1,0.8\\1,2,0\\2,0,0.4\\2,1,0.6\\2,2,0\\3,0,0\\3,1,0\\3,2,0\\% First 'row'
0,0,0.5\\0,1,4\\0,2,0\\1,0,0\\1,1,3\\1,2,0\\2,0,1\\2,1,2\\2,2,0\\3,0,4\\3,1,4\\3,2,0\\}\data
%\begin{animateinline}[controls,autopause,autoresume]{2}
% \multiframe{2}{blah=0+1}{%
\foreach \blah in {0,1}{
\pgfmathparse{\blah*\rowlength}
\let\startrow=\pgfmathresult
\pgfmathparse{\startrow+\rowlength-1}
\let\endrow=\pgfmathresult
\begin{tikzpicture}
\begin{axis}[
view={0}{90},
colorbar,
xtick=data,
xticklabels={NotGuilty,Corporal,Death,},
x tick label style={anchor=north,yshift=0cm,xshift=1.3cm},
ytick=data,
y tick label style={anchor=east,yshift=1.3cm,xshift=0cm},
yticklabels={BreakingPeace,Damage,}
]
\addplot3[
surf,
shader=flat corner,
% mesh/rows=4,
mesh/cols=3,
mesh/ordering=rowwise,
select coords between index={\startrow}{\endrow}
] table {\data};
\end{axis}
\end{tikzpicture}
}
%\end{animateinline}
\end{document}
仍然在自我拍拍,
我找不到上述问题的解决方案,因此我使用 python 和一些正则表达式查找和替换将所有数据放置在预期的格式中,给出以下解决方案:
使用:
% Style to select only points from #1 to #2 (inclusive), needed by animate
\pgfplotsset{select coords between index/.style 2 args={
x filter/.code={
\ifnum\coordindex<#1\def\pgfmathresult{}\fi
\ifnum\coordindex>#2\def\pgfmathresult{}\fi
}
}}
从https://tex.stackexchange.com/a/199396/4621
\newcommand{\offencepunishmentGridAnimation}{
\pgfplotstableread{Resources/Data/Plots/OffPunMatrix.csv}\data
\newcommand{\rowlength}{80}
\begin{figure}[!htb]
\begin{animateinline}[controls,autopause,autoresume]{2}
\multiframe{119}{i=0+1}{%
% \foreach \i in {0}{
\pgfmathparse{\i*\rowlength}
\let\startrow=\pgfmathresult
\pgfmathparse{\startrow+\rowlength-1}
\let\endrow=\pgfmathresult
\tikzsetnextfilename{OffPunMatrix\i}
\begin{tikzpicture}
\begin{axis}[
view={0}{90},
colorbar,
xtick=data,
xticklabels={BreakingPeace,Damage,Deception,Kill,Misc.,RoyalOffence,Sexual,Theft,ViolentTheft},
x tick label style={anchor=west,rotate=-45,yshift=0cm,xshift=0.2cm},
ytick=data,
y tick label style={anchor=east,yshift=0.5cm,xshift=0cm},
yticklabels={NotGuilty,Corporal,Death,Imprison,MiscPunish,NoPunish,Transport},
point meta max=0.7071,
point meta = sqrt(z),
colorbar style={
% ylabel=Probability,
ytick={0,0.14,0.28,0.42,0.56,0.7},
yticklabels = {0,0.1,0.2,0.3,0.4,0.5},
}
]
\addplot3[
surf,
shader=flat corner,
% mesh/rows=8,
mesh/cols=8,
mesh/ordering=rowwise,
select coords between index={\startrow}{\endrow}
] table {\data};
\end{axis}
\draw[black,line width = 1] (0,9) node[left] {Year\ }--(11.6,9);
\pgfmathparse{int(1674+2*\i)}
\let\year=\pgfmathresult
\fill (0.09747899159663865546*\i,9) circle (2pt) node[above] {\year};
\end{tikzpicture}
}
\end{animateinline}
\caption[Offence Punishment grid]{Offence punishment grid animation, where the colour in a square represents the estimate for the occurence.}
\label{anim:offpungrid}
\end{figure}
}
数据文件如下所示:
0,0,0.0148148148148
0,1,0.00740740740741
0,2,0.00740740740741
0,3,0.00740740740741
0,4,0.0148148148148
0,5,0.00740740740741
0,6,0.00740740740741
0,7,0
1,0,0.0148148148148
1,1,0.00740740740741
1,2,0.00740740740741
1,3,0.00740740740741
1,4,0.00740740740741
1,5,0.00740740740741
1,6,0.00740740740741
1,7,0
2,0,0.00740740740741
2,1,0.0148148148148
2,2,0.00740740740741
2,3,0.00740740740741
2,4,0.0148148148148
2,5,0.00740740740741
2,6,0.00740740740741
2,7,0
3,0,0.0148148148148
3,1,0.00740740740741
3,2,0.0814814814815
3,3,0.00740740740741
3,4,0.00740740740741
3,5,0.00740740740741
3,6,0.00740740740741
3,7,0
4,0,0.00740740740741
4,1,0.00740740740741
4,2,0.0148148148148
4,3,0.00740740740741
4,4,0.0148148148148
4,5,0.00740740740741
4,6,0.00740740740741
4,7,0
5,0,0.0222222222222
5,1,0.0148148148148
5,2,0.0222222222222
5,3,0.00740740740741
5,4,0.0222222222222
5,5,0.00740740740741
5,6,0.00740740740741
5,7,0
6,0,0.037037037037
6,1,0.00740740740741
6,2,0.00740740740741
6,3,0.00740740740741
6,4,0.0148148148148
6,5,0.00740740740741
6,6,0.00740740740741
6,7,0
7,0,0.0740740740741
7,1,0.0296296296296
7,2,0.148148148148
7,3,0.00740740740741
7,4,0.0222222222222
7,5,0.00740740740741
7,6,0.0222222222222
7,7,0
8,0,0.0296296296296
8,1,0.00740740740741
8,2,0.0296296296296
8,3,0.00740740740741
8,4,0.0148148148148
8,5,0.00740740740741
8,6,0.00740740740741
8,7,0
9,0,0
9,1,0
9,2,0
9,3,0
9,4,0
9,5,0
9,6,0
9,7,0
0,0,0.00595238095238
0,1,0.00595238095238
0,2,0.0119047619048
0,3,0.00595238095238
0,4,0.00595238095238
0,5,0.00595238095238
0,6,0.00595238095238
0,7,0
1,0,0.0119047619048
1,1,0.00595238095238
1,2,0.00595238095238
1,3,0.00595238095238
1,4,0.00595238095238
1,5,0.00595238095238
1,6,0.00595238095238
1,7,0
2,0,0.00595238095238
2,1,0.0119047619048
2,2,0.00595238095238
2,3,0.00595238095238
2,4,0.00595238095238
2,5,0.00595238095238
2,6,0.00595238095238
2,7,0
3,0,0.10119047619
3,1,0.00595238095238
3,2,0.0238095238095
3,3,0.00595238095238
3,4,0.0238095238095
3,5,0.00595238095238
3,6,0.00595238095238
3,7,0
4,0,0.0119047619048
4,1,0.00595238095238
4,2,0.0119047619048
4,3,0.00595238095238
4,4,0.00595238095238
4,5,0.00595238095238
4,6,0.00595238095238
4,7,0
5,0,0.0357142857143
5,1,0.0119047619048
5,2,0.0119047619048
5,3,0.00595238095238
5,4,0.0178571428571
5,5,0.00595238095238
5,6,0.00595238095238
5,7,0
6,0,0.0297619047619
6,1,0.00595238095238
6,2,0.0357142857143
6,3,0.00595238095238
6,4,0.0119047619048
6,5,0.00595238095238
6,6,0.00595238095238
6,7,0
7,0,0.190476190476
7,1,0.0178571428571
7,2,0.0833333333333
7,3,0.00595238095238
7,4,0.047619047619
7,5,0.00595238095238
7,6,0.0119047619048
7,7,0
8,0,0.0238095238095
8,1,0.00595238095238
8,2,0.0178571428571
8,3,0.00595238095238
8,4,0.00595238095238
8,5,0.00595238095238
8,6,0.00595238095238
8,7,0
9,0,0
9,1,0
9,2,0
9,3,0
9,4,0
9,5,0
9,6,0
9,7,0
等等。希望有一天这能对某人有所帮助,并且也许能激发出更简单的解决方案pgfplots
。