先来说说南丁格尔玫瑰图来源,南丁格尔玫瑰图,由南丁格尔发明(Nightingale) ,全名:Floarence Nightinggale,英国护士和统计学家。玫瑰图为南丁格尔在英国军营工作时所发明,当时她收集了在克里米亚战争时期的士兵在不同月份的死亡率和原因分布,通过可视化的方式有效的打动了当时的高层管理人员,包括维多利亚女王本人,于是医疗改良的提案才受到了大力的支持,将士兵的死亡率从42%降低至2%。玫瑰花图也有另外一个别名叫鸡冠花图(Coxcomb)。一些背景介绍如下截图:
南丁格尔玫瑰图类似于我们饼图的变形,只不过在表示占比的同时,扇形面积的比较也能体现另外的维度。然而试想一下,如果饼图本身的维度特别多,那么再加上扇形面积的大小不同,图形本身除了炫酷以外,从信息容易接受的角度来看,很难帮助读者有效捕捉到视图信息。目前我看到的玫瑰图,绝大部分扇形的角度都是均等的,特别多的场景是用于一个完整时间段内的某种信息表示,例如一天的24小时内的用户访问的 行为 。
接下来到实践环节,这个图该怎么做?在说明具体步骤之前,我们还是搞清楚逻辑。
先从Tableau实现来看:其实是做了坐标,将坐标连线点后做好的一个多边形,那么数据结构里除了需要有每个点的坐标,还需要知道点之间的先后连接顺序。
具体到每一个扇形,简单点来说最少通过如下四个点的连线来实现。
然而,此时你可能要反驳我说②和③连起来也不会是一个弧形,应该是一个直线,那么其实很简单,我们让②和③之间再多描上去一些点,之后彼此相连不就像一个弧形了么。
那接下来我们的问题转化为这些点的坐标怎么得到(接下来会有各种数学了,不过do not worry)。
首先让我们回想下坐标下圆的坐标和角度之间的关系(r代表圆半径,alpha代表弧度)。
x = r*cos(alpha)
y = r*sin(alpha)
r是扇形的半径,很明显在玫瑰图里面r和我们的面积成正比。假如让面积数值和面积代表的度量值相等。那么知道面积,我们需要知道扇形的角度那么角度怎么算?假如数据样式结构如下
数据有12个维度,目前我让每个维度占据同样的角度,也就是360/12,换成计算公式360/countd([Dimension Member])。扇形的面积S=[Measure]={360/countd([Dimension Member])}/360}*πr^2。那么r=SQRT([Measure]*countd([Dimension
Member])/π)(其中SQRT代表开方)
r的问题搞定了,我们来解决alpha。
既然每个扇形所占角度一致,那么每个扇形连线所用的点,也就是下图中2这个点的角度也很容易:m=((360/countd(Dimension Member))*(Dimension Member]-1))。那么3,4,5…12这些点的角度怎么算。3-12把扇形切分成了10等分,2到3的角度增长也就是n=扇形角度/10。若讲1-13命名为[PathID]那么从2到3增长的角度用公式表示:n=(([PathID]-2)*(360/
countd(Dimension Member)/10)。
那么任意一个点的角度可以表示为:m+n=((360/countd(Dimension Member))*(Dimension Member]-1))
角度知道了再除以180乘以π就转变成弧度,也就是我们一开始说的alpha。
1.原始数据
2.计算出来有多少不同的Dimension Member
3.将2中算好的维度数Number of Segment新建一列附到数据后方:
4.此时,我们需要把每个扇形描绘出来的1-13个点做出来,用alteryx实现很简单,通过新建行的工具。将初始值定义为1,约束条件为小于等于13,条件为每一个循环上都对该内容+1。
得到数据结果:
5.接下来内容是算出来1-13的坐标。用了几个计算公式。
首先就是角度,这里需要特殊说明,因为1和13是原点,那么角度为0,于是有了如下条件语句。
有了角度后我们算出弧度:
上面计算的PI()就是π的函数表示
接下来算出来半径:
X和Y的坐标,还是要特别注意1和13这两个点为0。Y就是X计算公式里换成sin。
6.最后将数据结果保存为Tableau的数据格式tde
Tableau打开的数据如下:
7.Tableau里四次鼠标拖拽就搞定。将xy坐标分别拖到行列上,将Dimension放到细节,图表样式选择多边形,将PathID放到路径上,再将Dimension Member放到维度是就大功告成了。
matlab源代码:function plot_rosedraw_main(450,90)
function draw_main(x,y)
%粉红色玫瑰
arcdata{1}=[65 -60 150 350 8
66 -54 300 470 8
65 -56 30 230 10
64 -57 300 490 17]
ellipsedata{1}=[73 -30 250 450 27 40
59 -30 100 290 27 40
65 -40 140 270 20 30]
arcdata{2}=[0 0 150 350 12
1 8 280 470 12
0 2 30 230 16
0 3 80 240 28
2 8 180 330 22
-2 2 310 460 25]
ellipsedata{2}=[-12 30 120 300 30 40
10 28 250 423 30 42
-4 10 290 393 30 40]
ellipsedata{3}=[120 5 0 360 15 25]
ellipsedata{4}=[-70 10 0 360 14 20]
rose_e{2}=[x+16 y+32 235 355 26 35
x-15 y+32 190 310 30 35
x+0 y+35 190 350 43 50]
rose_e{1}=[x+80 y-48 220 350 22 50
x+50 y-48 190 320 22 50
x+65 y-28 180 360 36 50]
rose_e{3}=[x+120 y-6 200 340 17 25
x+120 y+7 160 380 17 27]
rose_e{4}=[x-70 y+15 140 390 17 20
x-75 y-10 205 340 10 30
x-60 y-10 195 340 5 30]
arcdata{3}=[0 82 190 350 6]
ss={'m','r','b','y'}
s0={'k','k','g'}
figure('menubar','none','numbertitle','off','name','rose')
% figure('numbertitle','off','name','rose')
hold on
for j=1:length(ellipsedata)
for i=1:size(ellipsedata{j},1)
rectangle('Position',[x+ellipsedata{j}(i,1)-ellipsedata{j}(i,5),y+ellipsedata{j}(i,2)-ellipsedata{j}(i,6),2*ellipsedata{j}(i,5),2*ellipsedata{j}(i,6)],'Curvature',[1,1],...
'FaceColor',ss{j})
end
if j<4
for i=1:size(arcdata{j},1) draw_arc(x+arcdata{j}(i,1),y+arcdata{j}(i,2),arcdata{j}(i,3),arcdata{j}(i,4),arcdata{j}(i,5),s0{j})
end
end
for i=1:size(rose_e{j},1)
plot_rose_e(rose_e{j},j)
end
end
for j=1:3
zhuzhi=[x-98,y+100+j,255,371,100,80
x-20,y+30+j,260,358,140,140
x+224,y+20+j,180,218,160,140]
draw_branch(zhuzhi)
end
ce_branch=[x+70,y+34,180,233,140,140
x,y+40,205,255,100,120
x+135,y-30,209,249,72,120
x,y+20,263,301,100,120
x+85,y-10,278,305,100,120
x+100,y-62,282,308,90,120
x-50,y-10,277,314,30,120
x+70,y+80,222,266,52,120
x-60,y-45,229,266,52,120
x+79,y-45,229,266,52,120
x+84,y,224,273,52,120
x+110,y+40,240,282,100,120]
draw_branch(ce_branch)
t_leaf=[x+168,y+282,10,20,-40
x+160,y+252,8,16,260
x+145,y+270,8,16,-15
x+156,y+224,10,20,-45
x+150,y+200,8,16,270
x+135,y+220,8,16,-10
x+146,y+144,8,16,-80
x+130,y+130,6,12,235
x+125,y+154,7,14,-10
x+78,y+98,6,12,-90
x+60,y+90,5,10,180
x+70,y+109,5,10,-45
x-125,y+270,12,24,60
x-95,y+270,10,20,10
x-110,y+245,10,20,90
x-105,y+220,10,20,45
x-100,y+190,8,16,135
x-75,y+210,8,16,-45
x+65,y+190,10,20,-45
x+40,y+185,8,16,0
x+55,y+165,8,16,90]
for j=1:size(t_leaf,1)
draw_elli(t_leaf(j,1),t_leaf(j,2),t_leaf(j,3),t_leaf(j,4),t_leaf(j,5))
end
axis ij
axis off
set(gcf,'color','k')
daspect([1,1,1])
% 画旋转椭圆
function draw_elli(x0,y0,a,b,theta)
theta=-theta
t = 0:0.01:2*pi
x = a*cos(t)
y = b*sin(t)
xy = zeros(2,length(t))
for i = 1:length(t)
xy(:,i) = expm([0,-pi/180*thetapi/180*theta,0])*[x(i)y(i)]
end
plot(x0 +xy(1,:),480-y0 + xy(2,:),'g')
% 画弧线
function draw_arc(x0,y0,st_a,en_a,r,c_c)
t = (pi/180*st_a:0.01:pi/180*en_a)-pi
x = x0 + r*cos(t)
y = y0 + r*sin(t)
plot(x,y,c_c)
% 花萼
function plot_rose_e(matr,ch)
x=[]y=[]n=size(matr,1)
for i=1:size(matr,1)
t=(matr(i,3):matr(i,4))*pi/180-pi
x1=matr(i,1)+matr(i,5)*cos(t)
y1=matr(i,2)+matr(i,6)*sin(t)
if i<3
x1=2*matr(i,1)-x1
end
x1=fliplr(x1)
y1=fliplr(y1)
if n<3 &&i<2
x1=fliplr(x1)
y1=fliplr(y1)
end
if ch==4 &&i==2
x1=fliplr(x1)
y1=fliplr(y1)
end
x=[x,x1]
y=[y,y1]
end
fill(x,y,'g')
% 画树枝
function draw_branch(zhuzhi)
for k=1:size(zhuzhi,1)
t=(zhuzhi(k,3):zhuzhi(k,4))*pi/180-pi
x1=zhuzhi(k,1)+zhuzhi(k,5)*cos(t)
y1=zhuzhi(k,2)+zhuzhi(k,6)*sin(t)
x1=2*zhuzhi(k,1)-x1
plot(x1,y1,'g','linewidth',2)
end
只求第一象限部分,然后3倍S=3∫[0--->π/3] a²sin²3θ dθ=(3a²/2)∫[0--->π/3] (1-cos6θ) dθ=(3a²/2)(θ-(1/6)sin6θ) |[0--->π/3]=(3a²/2)*(π/3)=πa²/2
扩展资料:
package epm.mp.gateway.util;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class Rose extends JFrame implements ComponentListener, ItemListener {private JComboBox comboboxColor;
// 颜色组合框
public Rose() { super("玫瑰线");
this.setSize(600, 400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
Object data[] = { Color.red, Color.green, Color.blue };
comboboxColor = new JComboBox(data);
//颜色组合框
comboboxColor.addItemListener(this);
//注册组合框的选择事件监听器
this.add(comboboxColor);
this.addComponentListener(this);
//注册框架窗口的选择事件监听器
this.setVisible(true);
this.validate();
//r=asin3θ
//转化为直角坐标系
// 输入下面程序用于输出三叶玫瑰线的图形,三叶玫瑰线的参数方程为:
// x = r * sin(3t)* cos(t);
//y = r *sin(3t) * sin(t)
//其中: 0 <= t <= 2 * 3.14159
//
public void paint(Graphics g)(paint(g,3);