我的目标是从数据集创建极坐标图,其中附加数据列定义从中心向外径向填充的颜色。这可以在 PGFPlots 中完成吗?
在下面的示例中,我创建了一个三列数据集,其中 x 是角度,y 是测量值,z 是我想通过着色包含的附加测量值。示例编译后,散点图中的标记颜色会发生变化。就着色而言,这就是我的目标:
\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{polar}
\usepackage{filecontents}
\def\mydata{mydata.csv}
\begin{filecontents*}{\mydata}
x,y,z
-80,5,0
-60,6,1
-40,2,2
-20,7,3
0,5,4
20,3,5
40,7,6
60,3,7
80,4,8
\end{filecontents*}
\begin{document}
\begin{tikzpicture}
\begin{polaraxis}[
% x-axis
xtick={-90, -45, 0, 45, 90},
% y-axis
ytick = {40, 80},
% limits
domain = -90:90, xmin = -90, xmax = 90,
% colors
colormap/viridis,
point meta min = 0, point meta max = 8,
]
\addplot[point meta = explicit, scatter, polar comb] table [x=x, y=y, meta=z, col sep=comma] {\mydata};
\end{polaraxis}
\end{tikzpicture}
\end{document}
我的目标不是给标记着色,而是从原点到 y 值填充该颜色,就像饼图一样。“极坐标梳”看起来很有希望,但我无法给梳线着色(只有标记),梳子也无法填充线条之间(即填充整个段)。我尝试了各种[fill=...]
选项,\addplot
但只能得到单一颜色填充。
答案1
我认为没有pgfplots
内置类似的东西。可以手动执行此操作,如下例所示,通过使用来自的宏从表中读取值pgfplotstable
,然后使用普通的 TikZ 绘制图表。我从中获得了从颜色图中提取颜色的方法https://tex.stackexchange.com/a/340346。
\documentclass{standalone}
\usepackage{xfp}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\def\mydata{mydata.csv}
\begin{filecontents*}{\mydata}
x,y,z
-80,5,0
-60,6,1
-40,2,2
-20,7,3
0,5,4
20,3,5
40,7,6
60,3,7
80,4,8
\end{filecontents*}
\pgfplotstableread[col sep=comma]{\mydata}\loadedtable
\begin{document}
\begin{tikzpicture}[
% radii are normalized to [0,1], so the scale will in effect set the radius of the longest slice
scale=5,
% from https://tex.stackexchange.com/a/340346
% Defines the colormap
/pgfplots/colormap/viridis,
slice/.style={/utils/exec={
% Defines a color "mapped color"
\pgfplotscolormapdefinemappedcolor{#1}},
fill=mapped color
}
]
% define half angle step
\pgfmathsetmacro\Dhalf{10}
% get number of data rows in table
\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro{\Nrows}{\pgfplotsretval-1}
% find min/max of z-column
\pgfmathsetmacro\ZMax{-1e3}
\pgfmathsetmacro\ZMin{1e3}
% https://tex.stackexchange.com/a/252360/
\pgfplotstableforeachcolumnelement{z}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\ZMax}{max(\ZMax,\cellValue)}}
\pgfplotstableforeachcolumnelement{z}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\ZMin}{min(\ZMin,\cellValue)}}
% calculate range of z-values
\pgfmathsetmacro\Zrange{\ZMax-\ZMin}
% find max radius
\pgfmathsetmacro\RMax{0}
\pgfplotstableforeachcolumnelement{y}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\RMax}{max(\RMax,\cellValue)}}
% draw axis and ticks
% if you want these on top of the circle sectors, move the code to the end
\pgfmathsetmacro\AxisRadius{1.1}
\draw (0,0) -- (0,\AxisRadius) arc[start angle=90,delta angle=-180,radius=\AxisRadius] -- cycle;
\foreach \A in {-90,-45,...,90}
\draw [very thin, gray] (0,0) -- (\A:\AxisRadius*1cm+1pt) node [black, circle,anchor=\A+180] {$\A$};
% loop over the table
\foreach \N in {0,...,\Nrows}{
% read x-value from table
\pgfplotstablegetelem{\N}{x}\of\loadedtable
\pgfmathsetmacro{\tmpX}{\pgfplotsretval}
% read y-value from table
\pgfplotstablegetelem{\N}{y}\of\loadedtable
\pgfmathsetmacro{\tmpY}{\pgfplotsretval/\RMax}
% read z-value from table
\pgfplotstablegetelem{\N}{z}\of\loadedtable
\pgfmathsetmacro{\tmpZ}{\pgfplotsretval}
% \pgfplotscolormapdefinemappedcolor takes a number between 0 and 1000 as input.
% scale the given z-value based on the range of values
\newcommand{\tmpClr}{\fpeval{(\tmpZ-\ZMin)/\Zrange*1000}}
% make the slice
\fill [slice=\tmpClr] (0,0) -- (\tmpX-\Dhalf:\tmpY) arc[start angle=\tmpX-\Dhalf, delta angle=2*\Dhalf, radius=\tmpY] -- cycle;
}
\end{tikzpicture}
\end{document}
第二轮
\documentclass{standalone}
\usepackage{xfp}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\def\mydata{mydata.csv}
\begin{filecontents*}{\mydata}
x,y,z
-80,5,0
-60,6,1
-40,2,2
-20,7,3
0,5,4
20,3,5
40,7,6
60,3,7
80,4,8
\end{filecontents*}
\pgfplotstableread[col sep=comma]{\mydata}\loadedtable
\begin{document}
\begin{tikzpicture}[
% radii are normalized to [0,1], so the scale will in effect set the radius of the longest slice
scale=5,
% from https://tex.stackexchange.com/a/340346
% Defines the colormap
/pgfplots/colormap/viridis,
slice/.style={/utils/exec={
% Defines a color "mapped color"
\pgfplotscolormapdefinemappedcolor{#1}},
fill=mapped color
}
]
% define half angle step
\pgfmathsetmacro\Dhalf{10}
% get number of data rows in table
\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro{\Nrows}{\pgfplotsretval-1}
% find min/max of z-column
\pgfmathsetmacro\ZMax{-1e3}
\pgfmathsetmacro\ZMin{1e3}
% https://tex.stackexchange.com/a/252360/
\pgfplotstableforeachcolumnelement{z}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\ZMax}{max(\ZMax,\cellValue)}}
\pgfplotstableforeachcolumnelement{z}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\ZMin}{min(\ZMin,\cellValue)}}
% calculate range of z-values
\pgfmathsetmacro\Zrange{\ZMax-\ZMin}
% find max radius
\pgfmathsetmacro\RMax{0}
\pgfplotstableforeachcolumnelement{y}\of\loadedtable\as\cellValue{\pgfmathsetmacro{\RMax}{max(\RMax,\cellValue)}}
% draw axis and ticks
% if you want these on top of the circle sectors, move the code to the end
\pgfmathsetmacro\AxisRadius{1.05}
\draw (0,0) -- (0,\AxisRadius) arc[start angle=90,delta angle=-180,radius=\AxisRadius] -- cycle;
\foreach \A in {-80,-60,...,90}
\draw [very thin, gray] (0,0) -- (\A:\AxisRadius*1cm+1pt) node [black, circle,anchor=\A+180] {$\A$};
% loop over the table
\foreach [evaluate={\M=int(\N+1);\O=int(\N-1);}] \N in {0,...,\Nrows}{
% read x-value from table
\pgfplotstablegetelem{\N}{x}\of\loadedtable
\pgfmathsetmacro{\tmpX}{\pgfplotsretval}
% read y-value from table
\pgfplotstablegetelem{\N}{y}\of\loadedtable
\pgfmathsetmacro{\Rmid}{\pgfplotsretval/\RMax}
% read z-value from table
\pgfplotstablegetelem{\N}{z}\of\loadedtable
\pgfmathsetmacro{\tmpZ}{\pgfplotsretval}
% \pgfplotscolormapdefinemappedcolor takes a number between 0 and 1000 as input.
% scale the given z-value based on the range of values
\newcommand{\tmpClr}{\fpeval{(\tmpZ-\ZMin)/\Zrange*1000}}
\ifnum \N>0
\pgfplotstablegetelem{\O}{y}\of\loadedtable
\pgfmathsetmacro{\YPre}{\pgfplotsretval/\RMax}
\pgfmathsetmacro\Rpre{0.5*sqrt(\Rmid*\Rmid + \YPre*\YPre + 2*\Rmid*\YPre*cos(\Dhalf*2))}
\pgfmathsetmacro\AnglePre{atan2(0.5*(\Rmid*sin(\tmpX) + \YPre*sin(\tmpX-\Dhalf*2)), 0.5*(\Rmid*cos(\tmpX) + \YPre*cos(\tmpX-\Dhalf*2)))}
\fi
\ifnum \N<\Nrows
\pgfplotstablegetelem{\M}{y}\of\loadedtable
\pgfmathsetmacro{\YPost}{\pgfplotsretval/\RMax}
\pgfmathsetmacro\Rpost{sqrt(\Rmid*\Rmid + \YPost*\YPost + 2*\Rmid*\YPost*cos(\Dhalf*2))/2}
\pgfmathsetmacro\AnglePost{atan2(0.5*(\Rmid*sin(\tmpX) + \YPost*sin(\tmpX+\Dhalf*2)), 0.5*(\Rmid*cos(\tmpX) + \YPost*cos(\tmpX+\Dhalf*2)))}
\fi
\ifnum \N=0
\fill [slice=\tmpClr] (0,0) -- (\tmpX:\Rmid) -- (\AnglePost:\Rpost) -- cycle;
\else
\ifnum \N=\Nrows
\fill [slice=\tmpClr] (0,0) -- (\tmpX:\Rmid) -- (\AnglePre:\Rpre) -- cycle;
\else
\fill [slice=\tmpClr] (0,0) -- (\AnglePre:\Rpre) -- (\tmpX:\Rmid) -- (\AnglePost:\Rpost) -- cycle;
\fi
\fi
}
\end{tikzpicture}
\end{document}