# Problem drawing Kiviat diagram

From this post, I started to play with TikZ/PGF to draw a Kiviat Diagram froma a file .dat

Suppose to have two file table1.dat and table2.dat live these

%table1
column1 column2
8.109115e-001 3.446073e+000
3.971423e+000 3.740758e+000
1.556075e+000 2.252708e+000
2.642666e+000 4.191069e-001
8.282436e-001 1.144885e+000
3.009910e+000 4.566687e+000
1.314856e+000 7.618901e-001
3.270395e+000 4.129085e+000

%table2
colonna1 colonna2 colonna3 colonna4
4.073618e+000 4.785835e+000 3.393676e+000 3.474143e+000
4.528960e+000 2.426878e+000 3.788701e+000 1.585497e+000
6.349341e-001 4.001402e+000 3.715662e+000 4.751110e+000
4.566879e+000 7.094317e-001 1.961135e+000 1.722304e-001
3.161796e+000 2.108806e+000 3.277389e+000 2.193722e+000
4.877020e-001 4.578678e+000 8.559334e-001 1.907792e+000
1.392491e+000 3.961037e+000 3.530230e+000 3.827584e+000
2.734408e+000 4.797462e+000 1.591642e-001 3.976000e+000
4.787534e+000 3.278703e+000 1.384615e+000 9.343630e-001
4.824443e+000 1.785584e-001 2.308570e-001 2.448822e+000
7.880654e-001 4.245647e+000 4.856589e-001 2.227931e+000
4.852964e+000 4.669966e+000 4.117289e+000 3.231565e+000


Here it is the explained code:

\documentclass{report}

\usepackage{tikz}
\usetikzlibrary{calc}

\usepackage{pgfplotstable}

\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength{\PreviewBorder}{5mm}
\pagestyle{empty}

\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

% 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

% 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

\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

\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

\count1=0%\columnNumber
\count2=0%\axisNumber
\countdef\val=0

\loop
\ifnum\count1<\columnNumber

{\loop
\ifnum\count2<\axisNumber

\pgfplotstablegetelem{\count2}{[index]\count1}\of\table

\ifnum\pgfmathresult=1
\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)}

% COMPUTE THE GRID LINES NUMBER
\def\pitch{#4}

% AXIS LINE WIDTH
\def\lwidth{#5}

% COMPUTE OF THE ANGLE BETWEEN THE AXIS
\pgfmathsetmacro{\ang}{360/(\axisNumber+1)}

% 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}{
\foreach \tickPosition in {1,...,\numberTick}{
}
}

% TICK DRAWING
\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

}

% 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}
\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{tikzpicture}%[scale=.65]
\Kiviat{table1.dat}
{row1,row2,ro3,row4,row5,ro6,row7,row8}
{red,orange}
{.5}
{1}
\end{tikzpicture}

\begin{tikzpicture}%[scale=.65]
\Kiviat{table2.dat}
{row1,row2,row3,row4,row5,row6,row7,row8,ro9,row10,row11,row12}
{red,orange,green!50!black,yellow!70!black}
{.5}
{1}
\end{tikzpicture}

\end{document}


These are the results

For sure is not the best and more efficient code possible to write but it is a beginning.

Indeed, there is a big problem. If i scale the tikzpicture, not every component is scaled in the right way.

I'd like to introduce some pgfkeys to play with much more input. Can somebody help me?

• It is a little difficult to find out what your problem actually is. Please make sure it is more highlighted. You really should start with "I need help scaling the following TikZ picture ..." and have something like this also as title. – Martin Scharrer Feb 4 '11 at 13:27

I created a package to create tkz-kiviat diagram from a file.date . I add another example in this post how-to-draw-kiviat-diagrams

The example number 5 kiviat example used an external file. My package is based on TikZ and pgfplotstable.

:

You can see that I use a lot of options ans styles from TikZ

\begin{tikzpicture}
\tkzKiviatDiagramFromFile[
scale=.5,
label distance=.5cm,
gap     = 1,label space=3,
lattice = 10]{tableae.dat}
\tkzKiviatLineFromFile[thick,
color      = blue,
mark       = ball,
ball color = blue,
mark size  = 4pt,
fill       = blue!20]{tableae.dat}{2}
\tkzKiviatLineFromFile[thick,
color      = red,
mark       = ball,
ball color = red,
mark size  = 4pt,
fill       = red!20]{tableae.dat}{1}
\end{tikzpicture}


I've taken a different approach: I draw the plots using pgfplots, which makes it possible to use stuff like the legend functions and plot styles.

I have also assumed that the row and column titles are in the datafile. I'm not sure if that's what is going to be the case for you, but I thought that this would make it easier to plot different datasets. It should be easy enough to change to an argument similar to the one you used, though.

The plots are resizable through a scale factor that influences a base length in the plot. This keeps all the font sizes and line widths unchanged. If you want to actually scale everything down, you should go with what Martin suggested.

Maybe this approach is not what you need, but I think at least the algorithm for searching for the maximum value in a table using pgfplotstable should be useful.

\documentclass{minimal}

\usepackage{pgfplots}
\usepackage{listings}

\usepackage{pgfplotstable}

\begin{document}

\newcommand\kiviat[1]{
\def\filename{#1}

\pgfplotstablegetrowsof{\dataA} % Determine no. of rows
\pgfmathsetmacro{\rows}{\pgfplotsretval}
\pgfplotstablegetcolsof{\dataA} % Determine no. of cols
\pgfmathsetmacro{\cols}{\pgfplotsretval-1} % Correct offset
\pgfplotstablevertcat{\dataA}{\dataA} % Double the table to close gap after last point

% Not implemented: "\startingcol" could be used to switch between
%  row names in file and row names as argument
\def\startingcol{1}

% Find largest element
\pgfmathsetmacro\maxval{0}
\foreach \i in {\startingcol,...,\cols} {%
\pgfplotstablesort[sort key={[index] \i},sort cmp={float >}]\sorted{\dataA}
\pgfplotstablegetelem{0}{[index] \i}\of{\sorted}
\pgfmathsetmacro\newval{ceil(max(\pgfplotsretval,\maxval))}
\global\let\maxval=\newval
}

\pgfplotsset{every axis }

\tikzstyle{grid}=[gray]

% Draw the grid
\foreach \i in {1,...,\rows} {
\draw [grid,thick,->] (0,0) -- (\i/\rows*360:\radius+1em); % Spokes
\pgfplotstablegetelem{\i}{[index] 0}\of{\dataA}
% Spoke labels: some trigonometry to determine offset, needs tweaking
\pgfmathsetmacro\dist{abs(cos(\i/\rows*360)*3}
\node at (\i/\rows*360:\radius+\dist ex+1.5em) [anchor=center] {\pgfplotsretval};
% Points and grid lines
\foreach \j in {1,...,\maxval} {
\pgfmathsetmacro\nexti{\i+1}
}
}

% Tick labels
\foreach \j in {0,...,\maxval} {
\node [anchor=south west,inner xsep=0pt,inner ysep=2pt] at (0:\j*\radius/\maxval) {\j};
}

% The actual plot area
\begin{axis}[anchor=center,
xmin=-\maxval,xmax=\maxval,ymin=-\maxval,ymax=\maxval,
legend style={ at={(1.03,1.08)}, anchor=north west}
]
\foreach \n in {\startingcol,...,\cols} {
% pgfplots doesn't know polar coordinate systems, that's why we'll use cos and sin
\addplot +[no markers,thick] table [x expr=cos(\pgfplotstablerow/\rows*360)*\thisrowno{\n},y expr=sin(\pgfplotstablerow/\rows*360)*\thisrowno{\n}] {\dataA};
}
\end{axis}
}

\tikzstyle{every plot}+=[line width=2pt] % Can be used to influence plot style
\def\scalefactor{.65} % Scale factor multiplies the base length, everything else is relative to that
\begin{tikzpicture}
\kiviat{table1.dat}
\end{tikzpicture}

\tikzstyle{every plot}+=[line width=1pt]
\def\scalefactor{1}
\begin{tikzpicture}
\pgfplotsset{cycle list name=exotic}
\kiviat{table2.dat}
\end{tikzpicture}

\end{document


AFAIK you have to use the transform canvas option to scale complex tikzpictures, e.g. [transform canvas={scale=2}], otherwise only the coordinates are scaled. See section 22.4 "Canvas Transformations" in the pgfmanual.

You also can just put the whole picture in a \scalebox or \resizebox (graphicx package).

Update:

I tested your document now with [transform canvas={scale=2}]. The scaling seems work but the bounding box is gone. I would really suggest to use \scalebox or \resizebox as described for this question. They work fine.