我想使用存储在外部CSV
文件中的数据来填充 tikzpicture 矩阵内的节点。如果我的数据存储为x/y/z
,我可以编写以下循环(从这和这):
\documentclass{standalone}
\usepackage{tikz}
\usepackage{xcolor}
\usepackage{catchfile}
\newcommand\loaddata[1]{\CatchFileDef\loadeddata{#1}{\endlinechar=-1}}
\begin{filecontents*}{\jobname.dat}
1/1/20, 1/2/80, 1/3/20,
2/1/80, 2/2/100, 2/3/80,
3/1/20, 3/2/80, 3/3/20
\end{filecontents*}
\begin{document}
\begin{tikzpicture}
\loaddata{\jobname.dat}
\foreach \x/\y/\c in \loadeddata {
\pgfmathsetmacro\k{\c*1} % \c values could be transformed here
\fill[color=red!\k] (\x,\y) rectangle +(1,1);
}
\end{tikzpicture}
\end{document}
相反,我的数据存储为z
值矩阵(颜色强度),例如
\begin{filecontents*}{\jobname.csv}
20, 80, 20
80, 100, 80
20, 80, 20
\end{filecontents*}
请帮助我调整代码,以便我可以从文件中读取颜色,并且可以从矩阵内的单元格位置推断出x
和坐标。y
tikzpicture 看起来像这样:
答案1
第一个版本:数据矩阵的大小是已知且硬编码的(这里是一个3 x 3
矩阵):
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xcolor}
\usepackage{catchfile}
\usepackage{filecontents}
\newcommand\loaddata[1]{\CatchFileDef\loadeddata{#1}{\endlinechar=-1}}
\begin{filecontents*}{\jobname.csv}
2, 8, 2,
8, 10, 8,
2, 8, 2
\end{filecontents*}
\begin{document}
\def\MySpaceLength{3}
\begin{tikzpicture}
\loaddata{\jobname.csv}
\foreach \k[count=\i from 0] in \loadeddata{
\pgfmathsetmacro\myx{-3*int(\i/3)+\i}
\pgfmathsetmacro\myy{int(\i/3)}
\fill[color=red!\k] ({\MySpaceLength*\myx},-{\MySpaceLength*\myy}) rectangle+ ($(\MySpaceLength,\MySpaceLength)$);
}
\end{tikzpicture}
\end{document}
第二版本:矩阵的大小是已知的,由用户设置,但不是硬编码的。它存储在变量\XMatrixDimension
和中\YMatrixDimension
:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xcolor}
\usepackage{catchfile}
\usepackage{filecontents}
\newcommand\loaddata[1]{\CatchFileDef\loadeddata{#1}{\endlinechar=-1}}
\begin{filecontents*}{\jobname.csv}
2, 8, 2, 5,
8, 10, 8, 90,
2, 8, 2,60,
20, 2 , 56, 40,
30, 20, 50, 70
\end{filecontents*}
\begin{document}
\def\MySpaceLength{3}
\def\XMatrixDimension{4}
\def\YMatrixDimension{5}
\begin{tikzpicture}
\loaddata{\jobname.csv}
\foreach \k[count=\i from 0] in \loadeddata{
\pgfmathsetmacro\myx{-\XMatrixDimension*int(\i/\XMatrixDimension)+\i}
\pgfmathsetmacro\myy{int(\i/\XMatrixDimension)}
\fill[color=red!\k] ({\MySpaceLength*\myx},-{\MySpaceLength*\myy}) rectangle+ ($(\MySpaceLength,\MySpaceLength)$);
}
\end{tikzpicture}
\end{document}
输出:
答案2
以下是基于 pgfplots 附带的矩阵图的解决方案。它取自这个答案,其第二部分与koleygr 的回答。pgfplots 解决方案的优点是您可以使用颜色图来实现这一点。当然,您可以删除颜色条。
\documentclass[border=3.14mm,tikz]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{pgfplots.colormaps}
\pgfplotsset{compat=1.16}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.csv}
2, 8, 2
8, 10, 8
2, 8, 2
\end{filecontents*}
\newcommand*{\ReadOutElement}[4]{%
\pgfplotstablegetelem{#2}{[index]#3}\of{#1}%
\let#4\pgfplotsretval
}
\begin{document}
\pgfplotstableread[header=false,col sep=comma]{\jobname.csv}\datatable
\pgfplotstablegetrowsof{\datatable}
\pgfmathtruncatemacro{\numrows}{\pgfplotsretval}
\pgfplotstablegetcolsof{\datatable}
\pgfmathtruncatemacro{\numcols}{\pgfplotsretval}
\xdef\LstX{}
\xdef\LstY{}
\xdef\LstC{}
\foreach \Y [evaluate=\Y as \PrevY using {int(\Y-1)},count=\nY] in {1,...,\numrows}
{\pgfmathtruncatemacro{\newY}{\numrows-\Y}
\foreach \X [evaluate=\X as \PrevX using {int(\X-1)},count=\nX] in {1,...,\numcols}
{
\ReadOutElement{\datatable}{\PrevY}{\PrevX}{\Current}
\pgfmathtruncatemacro{\nZ}{\nX+\nY}
\ifnum\nZ=2
\xdef\LstX{\PrevX}
\xdef\LstY{\PrevY}
\xdef\LstC{\Current}
\else
\xdef\LstX{\LstX,\PrevX}
\xdef\LstY{\LstY,\PrevY}
\xdef\LstC{\LstC,\Current}
\fi
}
}
\edef\temp{\noexpand\pgfplotstableset{
create on use/x/.style={create col/set list={\LstX}},
create on use/y/.style={create col/set list={\LstY}},
create on use/color/.style={create col/set list={\LstC}},}}
\temp
\pgfmathtruncatemacro{\strangenum}{\numrows*\numcols}
\pgfplotstablenew[columns={x,y,color}]{\strangenum}\strangetable
%\pgfplotstabletypeset[empty cells with={---}]\strangetable
\begin{tikzpicture}
\pgfplotsset{%
colormap={WhiteRedBlack}{%
rgb255=(255,255,255)
rgb255=(255,0,0)
rgb255=(0,0,0)
},
}
\begin{axis}[%
small,
every tick label/.append style={font=\tiny},
tick align=outside,
minor tick num=5,
%
xlabel=$\beta$,
xticklabel pos=right,
xlabel near ticks,
xmin=-1, xmax=\numcols,
xtick={0, 5, ..., 4},
%
ylabel=$\alpha$,
ylabel style={rotate=-90},
ymin=-1, ymax=\numrows,
ytick={0, 5, ..., 4},
%
point meta min=0,
point meta max=32,
point meta=explicit,
%
%colorbar sampled,
colorbar as palette,
colorbar style={samples=3},
colormap name=WhiteRedBlack,
scale mode=scale uniformly,
]
\draw (axis description cs:0,0) -- (axis description cs:1,0);
\addplot [
matrix plot,
%mesh/cols=4,
point meta=explicit,
] table [meta=color,col sep=comma] \strangetable;
\end{axis}
\end{tikzpicture}
\end{document}