我在绘制雷达图时遇到了一些问题。
我想要绘制下面的图表。
我尝试粘贴在这里和那里找到的代码片段(我知道这不是一个好方法)并得到了以下结果。
有什么建议吗?
我花了一周的时间尝试做这件事。提前感谢您的帮助!!
使用的数据为:
colonna1 colonna2
4 12
3 2
.02 .1
代码如下:
\documentclass[a4paper,twoside,12pt]{book}
\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage[english]{babel}
\usepackage{pgfplotstable, pgfplots}
\begin{document}
\begin{tikzpicture}
\Kiviat{table.dat}
{C,N,P}
{red,orange}
{.5}
{.5}
\end{tikzpicture}
\end{document}
使用以下命令:
\makeatletter
\newcommand{\Kiviat}[5]{
% #1 - Table file
% #2 - List of the axis label. His lenght cannot be higher that the number of column of the table.
% It can be lower
% #3 - Color list. His lenght cannot be higher that the number of column of the table.
% It can be lower
% #4 - Pitch of th grid lines
% #5 - Axis line width
% LOAD TABLE
% The table must be n x m where each n column is the m plot in function of the angle.
% The first row(labeled by pgfplots table like 0) must contain the name of every column
\pgfplotstableread{#1}\table
% COMPUTETATION OF TABLE DIMENSION
%->number of axis
\pgfplotstablegetrowsof{\table}
\pgfmathsetmacro{\axisNumber}{\pgfplotsretval-1}
%\show\axisNumber
%-> number of the column to compute
\pgfplotstablegetcolsof{\table}
\pgfmathsetmacro{\columnNumber}{\pgfplotsretval-1}
%\show\columnNumber
% LOAD AXIS LABEL
\def\namesAxis{#2}
\foreach \x[count=\kk] in \namesAxis{}
\pgfmathparse{\kk<=(\axisNumber+1)}
\ifnum\pgfmathresult=0
\errmessage{The number of labels is greater that number of column of the table loaded}
\fi
% LOAD COLOR LIST
\def\listaColori{#3}
\foreach \mese[count=\numeroColori] in \listaColori{}
%\show\numeroColori
\pgfmathparse{\numeroColori<=(\columnNumber+1)}
\ifnum\pgfmathresult=0
\errmessage{Il numero dei colori è maggiore delle colonne dei dati}
\fi
% COMPUTE THE MAXIMUM ELEMENT INTO THE TABLE TO COMPUTE THE RADIUS OF KIVIAT DIAGRAM
% -> starting value
\def\maxRadius{0}
\count1=0%\columnNumber
\count2=0%\axisNumber
\countdef\val=0
\def\maxRadius{0}
\loop
\ifnum\count1<\columnNumber
\advance\count1 by 1
{\loop
\ifnum\count2<\axisNumber
\advance\count2 by 1
\pgfplotstablegetelem{\count2}{[index]\count1}\of\table
\pgfmathparse{\maxRadius<\pgfplotsretval}
\ifnum\pgfmathresult=1
\pgfmathsetmacro{\maxRadius}{\pgfplotsretval}
\node (Max) at (0,\maxRadius){};
\fi
\repeat}
\count2=0
\repeat
% now the value of the maximum value into the table is stored in coordinate y of (Max) point in pt units.
% It must be converted in unit less number in centimenter and saved into \radius variable
\pgfextracty{\pgf@x}{(Max)}
%pgfmathsetmacro{\radius}{}
\pgfmathsetmacro{\radius}{ceil(abs(\pgf@x)*2.54/72)}
% COMPUTE THE GRID LINES NUMBER
\def\pitch{#4}
\pgfmathsetmacro{\numberTick}{\radius/\pitch}
% AXIS LINE WIDTH
\def\lwidth{#5}
% COMPUTE OF THE ANGLE BETWEEN THE AXIS
\pgfmathsetmacro{\ang}{360/(\axisNumber+1)}
% COMPUTE OF TICK RADIUS
\pgfmathsetmacro{\tickRadius}{1.5*\lwidth}
% GRID DRAWING
\begin{pgfscope}
\pgfsetlinewidth{.5pt}
\pgfsetstrokecolor{gray!50}
\foreach \altezza in {0,1,...,\numberTick}{
\pgfmathsetmacro{\dist}{\altezza*\pitch}
\foreach \axis in {0,1,...,\axisNumber}{
\ifnum\axis=0
\pgfpathmoveto{\pgfpointpolar{\ang*(\axis+1)}{\dist cm}}%
\else
\pgfpathlineto{\pgfpointpolar{\ang*(\axis+1)}{\dist cm}}
\fi}
\pgfpathclose
\pgfusepath{stroke}
}
\end{pgfscope}
% AXIS and CIRCLE TICK DRAWING
\foreach \axis in {0,1,...,\axisNumber}{
\draw[->, line width=\lwidth pt] (0,0)--++(\ang*\axis:{\radius+1});
\foreach \tickPosition in {1,...,\numberTick}{
\fill (\ang*\axis:\pitch*\tickPosition)circle(\tickRadius pt);
}
}
% TICK DRAWING
\foreach \tick in {1,2,...,\radius}{
\node[anchor=south west] at (\tick,0){\tick};
}
% AXIS LABELING
\foreach \axis[count=\kk] in \namesAxis{
% \ang between 270 and 360
\pgfmathparse{(\ang*(\kk-1))<360&&(\ang*(\kk-1))>270}
\ifnum\pgfmathresult=1
\def\anchor{north west}
\fi
% \ang between 180 and 270
\pgfmathparse{(\ang*(\kk-1))<270&&(\ang*(\kk-1))>180}
\ifnum\pgfmathresult=1
\def\anchor{north east}
\fi
% \ang between 90 and 180
\pgfmathparse{(\ang*(\kk-1))<180&&(\ang*(\kk-1))>90}
\ifnum\pgfmathresult=1
\def\anchor{south east}
\fi
% \ang between 0 and 90
\pgfmathparse{(\ang*(\kk-1))<90&&(\ang*(\kk-1))>0}
\ifnum\pgfmathresult=1
\def\anchor{south west}
\fi
% \ang nei 4 punti cartinali
% east
\pgfmathparse{(\ang*(\kk-1))==0}
\ifnum\pgfmathresult=1
\def\anchor{west}
\fi
% nord
\pgfmathparse{(\ang*(\kk-1))==90}
\ifnum\pgfmathresult=1
\def\anchor{south}
\fi
% west
\pgfmathparse{(\ang*(\kk-1))==180}
\ifnum\pgfmathresult=1
\def\anchor{east}
\fi
% south
\pgfmathparse{(\ang*(\kk-1))==270}
\ifnum\pgfmathresult=1
\def\anchor{north}
\fi
\node[anchor=\anchor] at ({\ang*(\kk-1)}:{\radius+1}){\axis};
}
% FILE PLOTTING
\pgfplotstableforeachcolumn\table\as\nomeColonne{%
\begin{pgfscope}
% color definition
\pgfmathsetmacro{\cucu}{\pgfplotstablecol+1}
\foreach \var[count=\kk] in \listaColori{
\ifnum\kk=\cucu
\pgfsetstrokecolor{\var}
\fill[shift={(\radius cm+2 cm,-\pgfplotstablecol cm+\radius cm)},\var] (0,0)rectangle(.5,.1);
\node[shift={(\radius cm+2 cm,-\pgfplotstablecol cm+\radius cm)}, anchor=west] at (0,-.25){\nomeColonne};
\breakforeach
\fi
}
\foreach \axis in {0,1,...,\axisNumber}{
\pgfplotstablegetelem{\axis}{[index]\pgfplotstablecol}\of\table
\pgfmathsetmacro{\data}{\pgfplotsretval}
\ifnum\axis=0
\pgfpathmoveto{\pgfpointpolar{\ang*\axis}{\data cm}}%
\else
\pgfpathlineto{\pgfpointpolar{\ang*\axis}{\data cm}}
\fi
}
\pgfsetlinewidth{2pt}
\pgfclosepath
\pgfusepath{stroke}
\end{pgfscope}}
}
\makeatother
解决了:
\documentclass[a4paper,twoside,12pt]{book}
\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage[english]{babel}
\usepackage{pgfplotstable, pgfplots, filecontents}
\makeatletter
\newcommand{\Kiviat}[6]{
% #1 - Table file
% #2 - List of the axis label. His lenght cannot be higher that the number of column of the table.
% It can be lower
% #3 - Color list. His lenght cannot be higher that the number of column of the table.
% It can be lower
% #4 - Pitch of th grid lines
% #5 - Axis line width
% LOAD TABLE
% The table must be n x m where each n column is the m plot in function of the angle.
% The first row(labeled by pgfplots table like 0) must contain the name of every column
\pgfplotstableread{#1}\table
% COMPUTETATION OF TABLE DIMENSION
%->number of axis
\pgfplotstablegetrowsof{\table}
\pgfmathsetmacro{\axisNumber}{\pgfplotsretval-1}
%\show\axisNumber
%-> number of the column to compute
\pgfplotstablegetcolsof{\table}
\pgfmathsetmacro{\columnNumber}{\pgfplotsretval-1}
%\show\columnNumber
% LOAD AXIS LABEL
\def\namesAxis{#2}
\foreach \x[count=\kk] in \namesAxis{}
\pgfmathparse{\kk<=(\axisNumber+1)}
\ifnum\pgfmathresult=0
\errmessage{The number of labels is greater that number of column of the table loaded}
\fi
% LOAD COLOR LIST
\def\listaColori{#3}
\foreach \mese[count=\numeroColori] in \listaColori{}
%\show\numeroColori
\pgfmathparse{\numeroColori<=(\columnNumber+1)}
\ifnum\pgfmathresult=0
\errmessage{Il numero dei colori è maggiore delle colonne dei dati}
\fi
% COMPUTE THE MAXIMUM ELEMENT INTO THE TABLE TO COMPUTE THE RADIUS OF KIVIAT DIAGRAM
% -> starting value
\def\maxRadius{0}
\count1=0%\columnNumber
\count2=0%\axisNumber
\countdef\val=0
\def\maxRadius{0}
\loop
\ifnum\count1<\columnNumber
\advance\count1 by 1
{\loop
\ifnum\count2<\axisNumber
\advance\count2 by 1
\pgfplotstablegetelem{\count2}{[index]\count1}\of\table
\pgfmathparse{\maxRadius<\pgfplotsretval}
\ifnum\pgfmathresult=1
\pgfmathsetmacro{\maxRadius}{\pgfplotsretval}
\node (Max) at (0,\maxRadius){};
\fi
\repeat}
\count2=0
\repeat
% now the value of the maximum value into the table is stored in coordinate y of (Max) point in pt units.
% It must be converted in unit less number in centimenter and saved into \radius variable
\pgfextracty{\pgf@x}{(Max)}
%pgfmathsetmacro{\radius}{}
\pgfmathsetmacro{\radius}{ceil(abs(\pgf@x)*2.54/72)}
% COMPUTE THE GRID LINES NUMBER
\def\pitch{#4}
\pgfmathsetmacro{\numberTick}{\radius/\pitch}
% AXIS LINE WIDTH
\def\lwidth{#5}
% COMPUTE OF THE ANGLE BETWEEN THE AXIS
\pgfmathsetmacro{\ang}{360/(\axisNumber+1)}
% COMPUTE OF TICK RADIUS
\pgfmathsetmacro{\tickRadius}{1.5*\lwidth}
% GRID DRAWING
\begin{pgfscope}
\pgfsetlinewidth{.5pt}
\pgfsetstrokecolor{gray!50}
\foreach \altezza in {0,1,...,\numberTick}{
\pgfmathsetmacro{\dist}{\altezza*\pitch}
\foreach \axis in {0,1,...,\axisNumber}{
\ifnum\axis=0
\pgfpathmoveto{\pgfpointpolar{\ang*(\axis+1)}{\dist cm}}%
\else
\pgfpathlineto{\pgfpointpolar{\ang*(\axis+1)}{\dist cm}}
\fi}
\pgfpathclose
\pgfusepath{stroke}
}
\end{pgfscope}
% AXIS and CIRCLE TICK DRAWING
\foreach \axis in {0,1,...,\axisNumber}{
\draw[->, line width=\lwidth pt] (0,0)--++(\ang*\axis:{\radius+1});
\foreach \tickPosition in {1,...,\numberTick}{
\fill (\ang*\axis:\pitch*\tickPosition)circle(\tickRadius pt);
}
}
% TICK DRAWING
\pgfplotstableread{#6}\qwerty
\foreach \axis[count=\kk] in \namesAxis{
\foreach \tick in {1,2,3}{
\pgfplotstablegetelem{\kk}{\tick}\of\qwerty
\pgfmathsetmacro{\etichetta}{\pgfplotsretval}
\pgfmathsetmacro{\x}{\tick*cos((\ang*(\kk-1))}
\pgfmathsetmacro{\y}{\tick*sin((\ang*(\kk-1))}
\pgfmathparse{sin((\ang*(\kk-1))}
\node[anchor=south west] at (\x,\y){\etichetta};
}
}
% AXIS LABELING
\foreach \axis[count=\kk] in \namesAxis{
% \ang between 270 and 360
\pgfmathparse{(\ang*(\kk-1))<360&&(\ang*(\kk-1))>270}
\ifnum\pgfmathresult=1
\def\anchor{north west}
\fi
% \ang between 180 and 270
\pgfmathparse{(\ang*(\kk-1))<270&&(\ang*(\kk-1))>180}
\ifnum\pgfmathresult=1
\def\anchor{north east}
\fi
% \ang between 90 and 180
\pgfmathparse{(\ang*(\kk-1))<180&&(\ang*(\kk-1))>90}
\ifnum\pgfmathresult=1
\def\anchor{south east}
\fi
% \ang between 0 and 90
\pgfmathparse{(\ang*(\kk-1))<90&&(\ang*(\kk-1))>0}
\ifnum\pgfmathresult=1
\def\anchor{south west}
\fi
% \ang nei 4 punti cartinali
% east
\pgfmathparse{(\ang*(\kk-1))==0}
\ifnum\pgfmathresult=1
\def\anchor{west}
\fi
% nord
\pgfmathparse{(\ang*(\kk-1))==90}
\ifnum\pgfmathresult=1
\def\anchor{south}
\fi
% west
\pgfmathparse{(\ang*(\kk-1))==180}
\ifnum\pgfmathresult=1
\def\anchor{east}
\fi
% south
\pgfmathparse{(\ang*(\kk-1))==270}
\ifnum\pgfmathresult=1
\def\anchor{north}
\fi
\node[anchor=\anchor] at ({\ang*(\kk-1)}:{\radius+1}){\axis};
}
% FILE PLOTTING
\pgfplotstableforeachcolumn\table\as\nomeColonne{%
\begin{pgfscope}
% color definition
\pgfmathsetmacro{\cucu}{\pgfplotstablecol+1}
\foreach \var[count=\kk] in \listaColori{
\ifnum\kk=\cucu
\pgfsetstrokecolor{\var}
\fill[shift={(\radius cm+2 cm,-\pgfplotstablecol cm+\radius cm)},\var] (0,0)rectangle(.5,.1);
\node[shift={(\radius cm+2 cm,-\pgfplotstablecol cm+\radius cm)}, anchor=west] at (0,-.25){\nomeColonne};
\breakforeach
\fi
}
\foreach \axis in {0,1,...,\axisNumber}{
\pgfplotstablegetelem{\axis}{[index]\pgfplotstablecol}\of\table
\pgfmathsetmacro{\data}{\pgfplotsretval}
\ifnum\axis=0
\pgfpathmoveto{\pgfpointpolar{\ang*\axis}{\data cm}}%
\else
\pgfpathlineto{\pgfpointpolar{\ang*\axis}{\data cm}}
\fi
}
\pgfsetlinewidth{2pt}
\pgfclosepath
\pgfusepath{stroke}
\end{pgfscope}}
}
\makeatother
\begin{document}
\begin{filecontents*}{axis.dat}
3 6 9 1
1 2 3 23
.2 .4 .6 21
1 1 1 2
\end{filecontents*}
\begin{filecontents*}{coord.dat}
colonna1 colonna2
4 12
3 2
.02 .1
\end{filecontents*}
\begin{tikzpicture}
\Kiviat{coord.dat}{C,N,P}{red,orange}{1}{.5}{axis.dat}
\end{tikzpicture}
\end{document}
答案1
你可以用 绘制这个形状tikz-3dplot
。这是最终结果
我在 x 和 y 数据中添加了比例变量,以便您可以更改它们。
% scale your data
\def \yscal {0.5}
\def \xscal {2}
如果您想放大或缩小,请更改它们。这是适合您的情况的代码。
\documentclass{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{tikz}
\usepackage{tikz-3dplot}
% change the camera position
\tdplotsetmaincoords{40}{125}
\begin{document}
\begin{tikzpicture}[scale=.5,
x={(\raarot cm,\rbarot cm)},%
y={(\rabrot cm, \rbbrot cm)},%
z={(\racrot cm, \rbcrot cm)}]
% scale your data
\def \yscal {0.5}
\def \xscal {2}
\draw [->] (0,0,0) -- (5,0,0) node[anchor=west]{$x$};
\draw [->] (0,0,0) -- (0,\yscal*15,0) node[anchor=north west]{$y$};
\draw [->] (0,0,0) -- (0,0,5) node[anchor=west]{$z$};
\path [fill=red!50, opacity=.4]
(\xscal*1,0,0) -- (0,\yscal*12,0) -- (0,0,3) -- cycle;
\path [fill=green!50, opacity=.4]
(\xscal*.2,0,0) -- (0,\yscal*4,0) -- (0,0,3) -- cycle;
\path [fill=blue!50, opacity=.4]
(\xscal*1,0,0) -- (0,\yscal*12,0) -- (0,0,2) -- cycle;
% draw ticks in x-axis
\foreach \x in {0, 0.2, 0.4, 0.6,0.8, 1}
\draw [thin, gray] (\xscal*\x, -.1, 0) -- (\xscal*\x, .1, 0)
node[black,scale=.2,yshift=5mm,xshift=-5mm, rotate=-90] {\x};
% draw ticks in y-axis
\foreach \y in {0, 1, ..., 12}
\draw [thin, gray] (-.1, \yscal*\y, 0) -- (.1, \yscal*\y, 0)
node[black,scale=.2,yshift=3mm,xshift=3mm] {\y};
% draw ticks in z-axis
\foreach \z in {0,1, 2, 3}
\draw [thin, gray] (0, -.1, \z) -- (0, .1,\z)
node[black,scale=.2,yshift=0mm,xshift=-0mm] {\z};
\draw (0,0,3) node[scale=.7, right] {$v$};
\draw (0,\yscal*12,0) node[scale=.7, right] {$c$};
\draw (\xscal*1,0,0) node[scale=.7, below] {$p$};
\end{tikzpicture}
\end{document}