🔥 内容介绍

风玫瑰图是一种数据可视化工具,用于展示风向和风速的分布情况。它是一种极坐标图,以圆形为基础,将风向表示为角度,风速表示为半径。风玫瑰图通常用于气象学、地理学和环境科学领域,帮助研究人员和决策者更好地理解和分析风的特征和趋势。

风玫瑰图的基本原理是将一定时间内的风向和风速数据转换为可视化的图形。在图表的中心点,通常是一个圆圈或一个点,表示无风或风速非常低的情况。从中心点开始,每个方向的扇形区域代表该方向上的风向,扇形的大小则表示风速的大小。通常情况下,扇形区域的颜色或阴影也可以用来表示风速的强度。

风玫瑰图的优势在于它能够直观地展示风向和风速的分布情况。通过观察图表,我们可以很容易地看出哪个方向上的风速较高,哪个方向上的风速较低。同时,风玫瑰图还能够显示出风向和风速的频率分布,帮助我们了解不同风速区间的占比情况。

在气象学中,风玫瑰图被广泛应用于分析和研究气候变化、风暴活动以及风资源评估等领域。例如,在风能行业中,风玫瑰图可以帮助评估风能资源的分布情况,确定最佳的风能发电场址。此外,风玫瑰图还可以用于研究城市风环境,分析建筑物和城市规划对风速和风向的影响。

除了气象学领域,风玫瑰图还可以应用于其他领域,例如海洋学、航海和航空等。在海洋学中,风玫瑰图可以帮助研究海洋表面风的分布情况,对海洋环境和生态系统的研究具有重要意义。在航海和航空中,风玫瑰图可以用于船舶和飞机的航行计划,帮助确定最佳的航线和飞行高度,以提高安全性和效率。

尽管风玫瑰图在许多领域中都有广泛的应用,但它也存在一些限制。首先,风玫瑰图只能表示风向和风速的分布情况,无法提供其他气象要素的信息。其次,风玫瑰图对数据的质量和采样频率要求较高,如果数据不准确或不完整,可能会导致图表的误导。此外,风玫瑰图在表示大范围或复杂地形的风场时可能存在一定的局限性。

总的来说,风玫瑰图是一种强大的数据可视化工具,可以帮助我们更好地理解和分析风的特征和趋势。它在气象学、地理学和环境科学等领域中的应用广泛,并具有重要的研究和决策价值。然而,我们在使用风玫瑰图时需要注意数据的准确性和采样频率,以确保图表的可靠性和有效性。

📣 代码

Documentation: Wind rose as a scatter plot
Table of Contents
 Example 1: Individual sensors records on a single wind rose
 Example 2: Three-variate wind rose
 Example 1: Individual sensors records on a single wind rose
 Multiple sensors are consdiered. However, only 2 variables are represented.  Here we show the wind direction and the mean wind speed for 4 different wind sensors
clearvars;close all;clc;
Nsensors =4; % number of wind sensors
Nsamples = 100; % number of samples
COLOR = {'r','b','k','c','m','g'}; % color choice

% generation of records
Dir =[180,270,0,90]'*ones(1,Nsamples)+20.*randn(Nsensors,Nsamples); % #1 Mean wind direction
U = abs(1.*randn(Nsensors,Nsamples)+ ones(Nsensors,1)*linspace(5,20,Nsamples)); %#2 Mean wind  speed
name_U = '$\overline{u}$ (ms$^{-1}$)'; % #4 name of variable U
% plot the wind rose
jj=1;
figure
for ii=1:Nsensors,
    h{ii} = ScatterWindRose(Dir(ii,:),U(ii,:),'labelY',name_U);
    set(h{ii},'Marker','o','markerfacecolor',...
        COLOR{ii},'markeredgecolor','k')
  hold on
    leg{jj} = ['sensor ',num2str(jj)];
    jj=jj+1;
end
set(gcf,'color','w');
legend([h{:}],leg,'location','NorthEastOutside');

% put axis and text on top
th1 = findobj(gcf,'Type','text');
th2 = findobj(gcf,'Type','line');
for jj = 1:length(th1),
    uistack(th1(jj),'top');
end
for jj = 1:length(th2),
    uistack(th2(jj),'top');
end

% Adjust font size and name
set(findall(gcf,'-property','FontSize'),'FontSize',10,'fontName','Times')

 Example 2: Three-variate wind rose

Three variables are used hereafter:
The mean wind speed (Based on the 4 wind sensors from Example 1)
The turbulence intensity (TI)
The wind direction (Based on the 4 wind sensors from Example 1)
% TI is defined as:
TI =abs(0.05+abs(1./U)+0.03.*randn(size(U))); % #3 TI

% force column vectors: 
% we are not longer interested in identifying the sensors
Dir = Dir(:);
U=U(:);
TI = TI(:)*100;

%  We only want to look at TI lower than 30 %
indTI = find(TI>30);
U(indTI)=NaN;

% set limits and labels
limU = [min(U),max(U)]; % #3 limites for the wind speed
name_U = '$\overline{u}$ (ms$^{-1}$)'; % #4 name of variable U
name_IU = 'TI (\%)'; % #4 name of variable IU

% plot the data
figure
[h,c] = ScatterWindRose(Dir,U,'Ylim',limU,'labelY',name_U,'labelZ',name_IU,'Z',TI);
% c is the colorbr handle
% h is the scatter handle
% put axis and text on top
th1 = findobj(gcf,'Type','text');
th2 = findobj(gcf,'Type','line');
for jj = 1:length(th1)
    uistack(th1(jj),'top');
end
for jj = 1:length(th2)
    uistack(th2(jj),'top');
end

% Adjust the width of the colorbar
x1=get(gca,'position');
x=get(c,'Position');
x(4)= c.Position(4)/3; % three times thinner than initially
set(c,'Position',x)
set(gca,'position',x1)

% Adjust font size and name
set(findall(gcf,'-property','FontSize'),'FontSize',10,'fontName','Times')
function [varargout] =ScatterWindRose(X,Y,varargin)
%%
% [varargout] =ScatterWindRose(X,Y,varargin) creates a scatter polar plot
% with 2 to 3 variables as input
%
%% Input:
%varargin:1 to 6 inputs :
% #1 Direction ; type: float ; size: [1 x N] in DEGREES
% #2 variable associated to direction (ex: speed); type: float; size: [1 x N]
% #3 limits associated to #2; type: float ; size [1x2] -> if empty variable '[]' is written, the [min(#2),max(#2)] is used
% #4 name of variable #2; type: string;
% #5 variable associated to #2 and #1; type: float; size: [1 x N]
% #6 name of variable #5; type: string;
%
%% Syntax : 
% [hpol] =ScatterWindRose(Dir,U)
% [hpol,c] =ScatterWindRose(Dir,U)
%% OUTPUT
%optionals:
% varargout{1}: scatter handle
% varargout{2}: colorbar handle
% 
%% Author info
%Author: E. Cheynet, UiB, Norway
% Last modified: 2020-06-25

%% Input parser
% Number of outputs must be >=3and <=4.
nargoutchk(0,2)
% force columns vectors
X = X(:);    Y=Y(:);
X(X<0)=X(X<0)+360;

[cax,~,~] = axescheck(X);

% options: default values
p = inputParser();
p.CaseSensitive = false;
p.addOptional('Z',[]);
p.addOptional('Ylim',[min(Y),max(Y)]);
p.addOptional('labelZ','');
p.addOptional('labelY','');
p.addOptional('myMarker','+');
p.addOptional('myColor','k');
% p.addOptional('plotType','scatter');
p.parse(varargin{:});
% shorthen the variables name
labelZ = p.Results.labelZ;
labelY = p.Results.labelY;
Z = p.Results.Z(:);
myMarker = p.Results.myMarker;
myColor  = p.Results.myColor;
Ylim = p.Results.Ylim;
% plotType = p.Results.plotType;
%% Check errors
if Ylim(1)>Ylim(2),
    warning('you have specified Ylim(1)>Ylim(2); The two limits are flipped so that Ylim(1)<Ylim(2).');
elseif Ylim(1)==Ylim(2),
    error('you have specified Ylim(1)=Ylim(2). You need to choose Ylim(1)~=Ylim(2).');
end
if isnumeric(labelZ),    error('labelZ must be a string');end
if isnumeric(labelY),    error('labelY must be a string');end
if ischar(X) || ischar(Y)
    error('MATLAB:polar:InvalidInputType', 'Input arguments must be numeric.');
end
if ~isequal(size(X),size(Y))
    error('MATLAB:polar:InvalidInput', 'X and Y must be the same size.');
end
%% Initialisation of figure
% get hold state

cax = newplot(cax);
if ~ishold(cax);
    % make a radial grid
    hold(cax,'on');
    % Get limits
    Ymax = Ylim(2);
    Ymin = Ylim(1);
    % limits from Ymin to Ymax
    X = X(Y>= Ymin & Y<=Ymax);
    % limit from Zmin to Zmax, if variable Z is included
    if ~isempty(Z),
        Z = Z(Y>= Ymin & Y<=Ymax);
    end
    Y = Y(Y>= Ymin & Y<=Ymax);
    
    %% Create circles and radius
    % define a circle
    Ncirc = 4;
    createCircles(Ncirc,Ymax,Ymin,labelY)
    % create radius
    createRadius(Ymax,Ymin)
    % set view to 2-D
    view(cax,2);
    % set axis limits
    axis(cax,(Ymax-Ymin)*[-1 1 -1.15 1.15]);
    setappdata( cax, 'rMin', Ymin );
else
    %Try to find the inner radius of the current axis.
    if (isappdata ( cax, 'rMin' ) )
        Ymin = getappdata(cax, 'rMin' );
    else
        Ymin = 0;
    end
end
%%                  --------------------------
%                         PLOT the data
%                   --------------------------
% transform data to Cartesian coordinates.
xx = (Y - Ymin).*cosd(90-X);
yy = (Y - Ymin).*sind(90-X);
% plot data on top of grid
if ~isempty(Z),
    h = scatter(xx,yy,25,Z,'filled');
    set(h,'MarkerEdgeColor','k')
    c =colorbar;
    set(c,'location','NorthOutside','TickLabelInterpreter','latex');
    title(c,labelZ,'interpreter','latex')
else
    h = plot(xx,yy,[myMarker,myColor]);
end
if nargout == 1
    varargout{1} = h;
elseif nargout == 2
    varargout{1} = h;
    varargout{2} = c;
end


set(cax,'dataaspectratio',[1 1 1]), axis(cax,'off');
set(get(cax,'xlabel'),'visible','on')
set(get(cax,'ylabel'),'visible','on')
set(gcf,'color','w');
uistack(h, 'bottom')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Nested functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function createCircles(Ncirc,Ymax,Ymin,labelY)
        theta = linspace(0,360,100);
        xunit = cosd(theta);
        yunit = sind(theta);
        cos_scale = cosd(-20);
        sin_scale = sind(-20);
        % draw radial circles
        for ii = 1:Ncirc
            if ii<Ncirc
                COLOR = [0.5,0.5,0.5];
            else
                COLOR = [0.2 0.2 0.2];
            end
            line(xunit*ii.*(Ymax-Ymin)./Ncirc,...
                yunit*ii.*(Ymax-Ymin)./Ncirc,'color',COLOR,...
                'linestyle','-');
            if ii >= Ncirc,
                text(ii.*(Ymax-Ymin)./Ncirc.*cos_scale,...
                    ii.*(Ymax-Ymin)./Ncirc.*sin_scale, ...
                    [' ',num2str((Ymin+ii.*(Ymax-Ymin)./Ncirc),2),' ',...
                    '   ',...
                    labelY],'verticalalignment','bottom','interpreter','latex');
            else
                text(ii.*(Ymax-Ymin)./Ncirc.*cos_scale,...
                    ii.*(Ymax-Ymin)./Ncirc.*sin_scale, ...
                    [' ',num2str((Ymin+ii.*(Ymax-Ymin)./Ncirc),2)],...
                    'verticalalignment','bottom','interpreter','latex');
            end
        end
    end
    function createRadius(Ymax,Ymin)
        % origin aligned with the NORTH
        thetaLabel = [[90,60,30],[360:-30:120]];
        theta = 0:30:360;
        cs = [-cosd(theta); cosd(theta)];
        sn = [-sind(theta); sind(theta)];
        line((Ymax-Ymin)*cs,(Ymax-Ymin)*sn,'color',[0.5,0.5,0.5],...
            'linestyle','-')
        % annotate spokes in degrees
        rt = 1.1*(Ymax-Ymin);
        for iAngle = 1:numel(thetaLabel),
            if theta(iAngle) ==0,
                text(rt*cosd(theta(iAngle)),rt*sind(theta(iAngle)),'E',...
                    'horizontalalignment','center');
            elseif theta(iAngle) == 90,
                text(rt*cosd(theta(iAngle)),rt*sind(theta(iAngle)),'N',...
                    'horizontalalignment','center');
            elseif theta(iAngle) == 180,
                text(rt*cosd(theta(iAngle)),rt*sind(theta(iAngle)),'W',...
                    'horizontalalignment','center');
            elseif theta(iAngle) == 270,
                text(rt*cosd(theta(iAngle)),rt*sind(theta(iAngle)),'S',...
                    'horizontalalignment','center');
            else
                text(rt*cosd(theta(iAngle)),rt*sind(theta(iAngle)),int2str(abs(thetaLabel(iAngle))),...
                    'horizontalalignment','center');
            end
        end
        
    end
end

⛳️ 运行结果

Python 绘制 风向玫瑰图 箭头_ci