14

Can anybody please tell me how to do it? I can't find anything alike on the web nor stackexchange website. The most similar plot that I've found is this:

Which LaTeX package is needed to draw radar-like diagrams?

What I have to do is something like this:

Kind of Wind Rose

Here is some data table

enter image description here

  • 2
    Could you edit your question to include some example data that you'd like to plot? – Jake Sep 11 '15 at 12:52
  • 1
    Actually, I want to plot Wind Speed and Direction. I get the data from a weather station in the format (value[m/s], value[degrees]) where the first is the wind speed and the second the wind direction from 0 to 360. From that info you have to acquire the frequency and define which values goes to 'N' (north), 'S' (south), etcetera. So it needs a previous definition, I guess. I'll add some table with real data. – Cristóbal Sep 11 '15 at 13:38
  • Start with the outermost colors and work inwards. The tricky part will be adding all those different legends. – John Kormylo Sep 11 '15 at 15:21
  • The tricky part for me is making the 'bars' on to polar coordinates diagram. And then assigning the appropriate values to the direction letters (e.g., North is 360 and 0) – Cristóbal Sep 11 '15 at 15:24
  • 2
    alan wetmore gave a talk on wind roses with tikz at the 2013 tug meeting. unfortunately, he didn't produce a paper, and that year the talks weren't videoed. however, his slides have been posted, and may be of some help: http://tug.org/tug2013/slides/WetmoreTalk2013-10-24.pdf – barbara beeton Sep 11 '15 at 16:30
  • Very nice what Alan Wetmore did. Very helpful. Is there a way to contact him? thank you very much. – Cristóbal Sep 11 '15 at 18:27
  • There's an email address on the first slide. – Torbjørn T. Sep 11 '15 at 18:28

5 Answers5

10

For binning the data (i.e. calculating the histogram values), I would recommend using an external tool, like the Python library Pandas. For instance, if you have a data.dat file like what you'd download from the New Zealand Climate Database ...

Station,Date(NZST),Dir(DegT),Speed(m/s),Dir StdDev,Spd StdDev,Period(Hrs),Freq
3925,20150801:0000,0,0.0,23.0,0.1,1,H
3925,20150801:0100,156,0.2,35.0,0.3,1,H
3925,20150801:0200,97,0.3,16.0,0.4,1,H
3925,20150801:0300,139,0.3,15.0,0.4,1,H
3925,20150801:0400,315,0.4,51.0,0.5,1,H
...

... you can calculate the histogram using the following Python script:

import pandas as pd
data = pd.read_csv('data.dat', sep=',')
data['Dir(Rounded)'] = (data['Dir(DegT)']/(360/16)).round().mod(16)*360/16
frequencies = pd.crosstab(data['Dir(Rounded)'], pd.cut(data['Speed(m/s)'], bins)) / data['Dir(Rounded)'].size
frequencies.to_csv('frequencies.csv', sep='\t')

frequencies.csv then looks like this:

Dir(Rounded)    (0, 0.5]    (0.5, 2]    (2, 4]  (4, 6]  (6, 8]  (8, 10]
0.0 0.0228187919463 0.0496644295302 0.0134228187919 0.0 0.0 0.0
45.0    0.0174496644295 0.0510067114094 0.0604026845638 0.0308724832215 0.0 0.0
90.0    0.0362416107383 0.0751677852349 0.00268456375839    0.0 0.0 0.0
135.0   0.0389261744966 0.153020134228  0.0510067114094 0.0 0.0 0.0
180.0   0.0201342281879 0.0348993288591 0.0161073825503 0.0 0.0 0.0
225.0   0.0161073825503 0.0295302013423 0.00402684563758    0.0 0.0 0.0
270.0   0.0375838926174 0.0402684563758 0.00402684563758    0.0 0.0 0.0
315.0   0.0644295302013 0.102013422819  0.00134228187919    0.0 0.0 0.0

And this data file can then be plotted using PGFPlots:

\begin{tikzpicture}
\begin{polaraxis}[
    xtick={0,45,...,315},
    xticklabels={E,NE,N,NW,W,SW,S,SE},
    ytick=\empty,
    legend entries={0 to 0.5, 0.5 to 2, 2 to 4, 4 to 6},
    cycle list={cyan!20, cyan!50, cyan, cyan!50!black, cyan!20!black},
    legend pos=outer north east
]
\pgfplotsinvokeforeach{1,...,6}{
    \addplot +[polar bar=17, stack plots=y]
        table [x expr=-\thisrowno{0}+90, y index=#1] {frequencies.csv};
    }
\end{polaraxis}
\end{tikzpicture}

The polar bar style needs to be defined in the preamble of your document. Here's the full example .tex file:

\documentclass[]{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepgfplotslibrary{polar}
\pgfplotsset{compat=1.12}


\begin{document}
\makeatletter
\pgfplotsset{
    polar bar/.style={
        scatter,
        draw=none,
        mark=none,
        visualization depends on=rawy\as\rawy,
        area legend,
        legend image code/.code={%
            \fill[##1] (0cm,-0.1cm) rectangle (0.6cm,0.1cm);
        },
        /pgfplots/scatter/@post marker code/.add code={}{
            \pgfmathveclen{\pgf@x}{\pgf@y}
            \edef\radius{\pgfmathresult}
            \fill[]
                (\pgfkeysvalueof{/data point/x},-\pgfkeysvalueof{/data point/y})
                ++({\pgfkeysvalueof{/data point/x}-#1/2},\pgfkeysvalueof{/data point/y})
                arc [start angle=\pgfkeysvalueof{/data point/x}-#1/2,
                    delta angle=#1,
                    radius={\radius pt}
                ]
                -- +({\pgfkeysvalueof{/data point/x}+#1/2},-\rawy)
                arc [start angle=\pgfkeysvalueof{/data point/x}+#1/2,
                    delta angle=-#1,
                    radius={
                        (\pgfkeysvalueof{/data point/y} - \rawy) / \pgfkeysvalueof{/data point/y} * \radius pt
                    }
                ]
                --cycle;
        }
    },
    polar bar/.default=30
}

\begin{tikzpicture}
\begin{polaraxis}[
    xtick={0,45,...,315},
    xticklabels={E,NE,N,NW,W,SW,S,SE},
    ytick=\empty,
    legend entries={0 to 0.5, 0.5 to 2, 2 to 4, 4 to 6},
    cycle list={cyan!20, cyan!50, cyan, cyan!50!black, cyan!20!black},
    legend pos=outer north east
]
\pgfplotsinvokeforeach{1,...,6}{
    \addplot +[polar bar=17, stack plots=y]
        table [x expr=-\thisrowno{0}+90, y index=#1] {frequencies.csv};
    }
\end{polaraxis}
\end{tikzpicture}

\end{document}
Jake
  • 232,450
6

A rather short code with pst-plot:

\documentclass[x11names, border=2pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{pst-plot}
\usepackage{auto-pst-pdf}
\usepackage{array, siunitx} 

\begin{document}

\sffamily\setlength\tabcolsep{2pt}
\begin{pspicture}(-7,-7)(6,8)
\psset{xAxis=false, dy=1, Dy =4, subticks=4, ticksize=-4pt 0, mathLabel=false, labelFontSize=\footnotesize}
\psaxes{-}(-6.2,0)(-6.2,5)
\psaxes[Dy=-4, ylabelPos=l]{-}(-6.2,0)(-6.2,-5.035)
\rput{90}(-7,0){Frequency (per cent)}
%%%%%
\rput(6,5){\footnotesize\begin{tabular}{@{}l<{\rule[-0.2mm]{6mm}{3mm}}l@{}}\multicolumn{2}{c}{Wind speed}\\\multicolumn{2}{c}{(m/s)}\\[0.5ex]%
\color{red} & > 10\\ \color{Tan1} & 8 to10 \\ \color{Yellow1} & 6 to 8 \\ \color{Green4!80!} & 4 to 6 \\ \color{RoyalBlue3} & 2 to 4 \\ \color{Cyan1} & 0.5 to 2 \\ \color{Gold4} & < 0.5
\end{tabular}}
%%%%%
\rput(5.5,-5){\footnotesize\begin{tabular}{@{}ll@{}}
Mean speed &2.59\,m/s\\ Peak frequency: &18.64\,\%\\ Peak direction & NNW\\ Percent calm: &8.14\,\% \\
\multicolumn{2}{@{}l@{}}{Calm defined as < 0.5\,m/s}
\end{tabular}}
    \psset{axesstyle=polar, xsubticks=4,xsubtickcolor=LightSteelBlue4!60!, ysubticks=2, ysubtickwidth=0.4pt, ysubtickcolor =black, Dy=45, labels=none}
    \psaxes(5,360)
    \psset{unit=1.06cm}
    \rput(5,0){E}\rput{-67.5}(5;22.5){ENE}\rput{-45}(5.;45){NE}\rput{-22.5}(5;67.5){NNE}
    \rput(5;90){N}\rput{22.5}(5;112.5){NNW}\rput{45}(5;135){NW}\rput{67.5}(5;157.5){WNW}
    \rput(5;180){W}\rput{-67.5}(5;202.5){WSW}\rput{-45}(5.;225){SW}\rput{-22.5}(5;247.5){SSW}
    \rput(5;270){S}\rput{22.5}(5;292.5){SSE}\rput{45}(5;315){SE}\rput{67.5}(5;337.5){ESE}
    %%%%%%%%%%%%%%%
    \psset{unit=1cm}%l
    \pswedge*[linecolor=red]{4.7}{105}{120}
    \pswedge*[linecolor=Tan1]{4.65}{105}{120}
    \pswedge*[linecolor=Yellow1]{4.4}{105}{120}
    \pswedge*[linecolor=Green4!80!]{3.75}{105}{120}
    \pswedge*[linecolor=RoyalBlue3]{2.45}{105}{120}
    \pswedge*[linecolor=Cyan1]{0.85}{105}{120}
\end{pspicture}

\end{document} 

enter image description here

Bernard
  • 271,350
  • Very nice! this is taking form. But, the thing is that your using single data. How can you use data from a table, but not just that, at the same time, you need the frequency to be shown on the diagram as in the figure that I've attached in the first post. Freq is calculated over the table data and is that percentage what gives you the size and proportion of the colors. I don't know if I'm being clear about it. – Cristóbal Sep 11 '15 at 18:22
  • I began to make some computations with the data you posted, until I realised there were too few data to make something significant. Anyway, this is a statistics problem, not really a LaTeX problem. So I decided to copy part of your image to show what could be done, graphically speaking. I willadd the rest of the graphical elements later. – Bernard Sep 11 '15 at 18:28
  • @Cristóbal: I've added legends. – Bernard Sep 11 '15 at 21:42
2

Considering the amount of effort needed to get pgfplots to produce the tick labels, one might as well use plain tikz.

\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{polar}

\begin{document}
\begin{tikzpicture}
\begin{polaraxis}[ymax=20,yticklabel=\empty,xticklabel=\empty,
xtick={0,22.5,45,67.5,90,112.5,135,157.5,180,202.5,225,247.5,270,292.5,315,337.5}]
\coordinate (origin) at (axis cs:0,0);
\coordinate (E) at (axis cs:0,21.5);
\coordinate (ENE) at (axis cs:22.5,21.5);
\coordinate (NE) at (axis cs:45,21.5);
\coordinate (NNE) at (axis cs:67.5,21.5);
\coordinate (N) at (axis cs:90,21.5);
\coordinate (NNW) at (axis cs:112.5,21.5);
\coordinate (NW) at (axis cs:135,21.5);
\coordinate (WNW) at (axis cs:157.5,21.5);
\coordinate (W) at (axis cs:180,21.5);
\coordinate (WSW) at (axis cs:202.5,21.5);
\coordinate (SW) at (axis cs:225,21.5);
\coordinate (SSW) at (axis cs:247.5,21.5);
\coordinate (S) at (axis cs:270,21.5);
\coordinate (SSE) at (axis cs:292.5,21.5);
\coordinate (SE) at (axis cs:315,21.5);
\coordinate (ESE) at (axis cs:337.5,21.5);
\end{polaraxis}
\node at(E) {\scriptsize\textsf{E}};
\node[rotate=-67.5] at(ENE) {\scriptsize\textsf{ENE}};
\node[rotate=-45] at(NE) {\scriptsize\textsf{NE}};
\node[rotate=-22.5] at(NNE) {\scriptsize\textsf{NNE}};
\node at(N) {\scriptsize\textsf{N}};
\node[rotate=22.5] at(NNW) {\scriptsize\textsf{NNW}};
\node[rotate=45] at(NW) {\scriptsize\textsf{NW}};
\node[rotate=67.5] at(WNW) {\scriptsize\textsf{WNW}};
\node at(W) {\scriptsize\textsf{W}};
\node[rotate=-67.5] at(WSW) {\scriptsize\textsf{WSW}};
\node[rotate=-45] at(SW) {\scriptsize\textsf{SW}};
\node[rotate=-22.5] at(SSW) {\scriptsize\textsf{SSW}};
\node at(S) {\scriptsize\textsf{S}};
\node[rotate=22.5] at(SSE) {\scriptsize\textsf{SSE}};
\node[rotate=45] at(SE) {\scriptsize\textsf{SE}};
\node[rotate=67.5] at(ESE) {\scriptsize\textsf{ESE}};
\end{tikzpicture}
\end{document}

compass

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • Thank you very much for your answer. But now, how do you plot the data? and shall I use pst-plot or pgfplots? Though I think pst-plot looks much better. – Cristóbal Sep 11 '15 at 17:47
  • You could use addplot[fill between]. I tried using \fill but ran into some weird bug. Anyway, If I were to continue I would start over by drawing my own grid using tikz. It's just a bunch of circles and straight lines. – John Kormylo Sep 12 '15 at 00:08
1

The wheelchart package, which I wrote, can be used.

The data are first stored in the macro \WClist. Here, the first value corresponds to the gray part, the second value to the cyan part and so on till the last value which corresponds to the red part. Thereafter the abbreviation for the wind direction is added.

For each color, a separate \wheelchart is used. For example in the first \wheelchart, \WCstart is A and \WCend is B in the \foreach loop. Hence the key radius sets the inner radius to \WCvarA and the outer radius to \WCvarB. These correspond respectively to the first and second variable in the data from \WClist.

The key value=1 is used so that the angle of each slice is the same.

The gap between the slices is obtained with the key gap polar=3.

The wind directions are placed in the last \wheelchart. These are given by the ninth variable in \WClist thus we set data=\WCvarI. With data style{2,3,4,14,15,16}, the style for the data in slices 2, 3, 4, 14, 15 and 16 is determined and similarly for the slices 6, 7, 8, 10, 11 and 12.

enter image description here

\documentclass[border=6pt]{standalone}
\usepackage{wheelchart}
\begin{document}
\begin{tikzpicture}
\sffamily
\foreach\r in {1,...,5}{
  \draw (0,0) circle[radius=\r];
  \foreach\k in {0.25,0.5,0.75}{
    \draw[gray] (0,0) circle[radius={\r-\k}];
  }
}
\foreach\a in {0,22.5,...,157.5}{
  \draw (\a:-5)--(\a:5);
}
\def\WClist{%
  0/0.2/0.5/0.8/1.1/1.3/1.35/1.4/N,
  0/0.1/0.2/0.21/0.22/0.23/0.24/0.25/NNE,
  0/0.1/0.3/0.31/0.32/0.33/0.34/0.35/NE,
  0/0.1/0.5/0.51/0.52/0.53/0.54/0.55/ENE,
  0/0.1/0.5/0.7/0.8/0.81/0.82/0.83/E,
  0/0.15/0.7/1.3/1.8/2.1/2.2/2.3/ESE,
  0/0.2/1.4/1.8/1.9/1.91/1.92/1.93/SE,
  0/0.1/1.5/1.7/1.8/1.85/1.9/1.95/SSE,
  0/0.1/2.4/2.5/2.51/2.52/2.53/2.54/S,
  0/0.1/1.8/1.9/1.91/1.92/1.93/1.94/SSW,
  0/0.1/1.2/1.5/1.8/1.81/1.82/1.83/SW,
  0/0.1/0.8/1.4/1.5/1.51/1.52/1.53/WSW,
  0/0.1/0.5/1.2/1.4/1.41/1.42/1.43/W,
  0/0.1/0.4/1.3/1.6/1.7/1.71/1.72/WNW,
  0/0.1/0.5/1.4/1.9/2.1/2.2/2.21/NW,
  0/0.1/0.7/2.4/3.7/4.4/4.6/4.7/NNW%
}
\pgfkeys{
  /wheelchart,
  start half,
  value=1
}
\foreach\WCstart/\WCend/\WCcolor in {%
  A/B/gray,
  B/C/cyan,
  C/D/blue,
  D/E/green,
  E/F/yellow,
  F/G/orange,
  G/H/red%
}{
  \wheelchart[
    data=,
    gap polar=3,
    radius={\csname WCvar\WCstart\endcsname}{\csname WCvar\WCend\endcsname},
    slices style=\WCcolor
  ]{\WClist}
}
\wheelchart[
  data=\WCvarI,
  data style{2,3,4,14,15,16}={rotate={\WCmidangle-90},anchor=south},
  data style{6,7,8,10,11,12}={rotate={\WCmidangle+90},anchor=north},
  radius={0}{5},
  slices style={fill=none}
]{\WClist}
\end{tikzpicture}
\end{document}
matexmatics
  • 4,819
-1
\coordinate (origin) at (axis cs:0,0);
\coordinate (E) at (axis cs:0,21.5);
\coordinate (ENE) at (axis cs:22.5,21.5);
\coordinate (NE) at (axis cs:45,21.5);
\coordinate (NNE) at (axis cs:67.5,21.5);
\coordinate (N) at (axis cs:90,21.5);
\coordinate (NNW) at (axis cs:112.5,21.5);
\coordinate (NW) at (axis cs:135,21.5);
\coordinate (WNW) at (axis cs:157.5,21.5);
\coordinate (W) at (axis cs:180,21.5);
\coordinate (WSW) at (axis cs:202.5,21.5);
\coordinate (SW) at (axis cs:225,21.5);
\coordinate (SSW) at (axis cs:247.5,21.5);
\coordinate (S) at (axis cs:270,21.5);
\coordinate (SSE) at (axis cs:292.5,21.5);
\coordinate (SE) at (axis cs:315,21.5);
\coordinate (ESE) at (axis cs:337.5,21.5);
\end{polaraxis}
\node at(E) {\scriptsize\textsf{E}};
\node[rotate=-67.5] at(ENE) {\scriptsize\textsf{ENE}};
\node[rotate=-45] at(NE) {\scriptsize\textsf{NE}};
\node[rotate=-22.5] at(NNE) {\scriptsize\textsf{NNE}};
\node at(N) {\scriptsize\textsf{N}};
\node[rotate=22.5] at(NNW) {\scriptsize\textsf{NNW}};
\node[rotate=45] at(NW) {\scriptsize\textsf{NW}};
\node[rotate=67.5] at(WNW) {\scriptsize\textsf{WNW}};
\node at(W) {\scriptsize\textsf{W}};
\node[rotate=-67.5] at(WSW) {\scriptsize\textsf{WSW}};
\node[rotate=-45] at(SW) {\scriptsize\textsf{SW}};
\node[rotate=-22.5] at(SSW) {\scriptsize\textsf{SSW}};
\node at(S) {\scriptsize\textsf{S}};
\node[rotate=22.5] at(SSE) {\scriptsize\textsf{SSE}};
\node[rotate=45] at(SE) {\scriptsize\textsf{SE}};
\node[rotate=67.5] at(ESE) {\scriptsize\textsf{ESE}};
\end{tikzpicture}
\end{document}
KersouMan
  • 1,850
  • 3
  • 13
  • 15