我需要绘制三元/三角形图,表示各种物质/混合物的摩尔分数(x,y,z)(x + y + z = 1).每个图表示等值物质,例如具有相同熔点的物质.需要在具有不同颜色/符号的相同三角形上绘制图形,如果我还可以连接点,那将是很好的.
我看过matplotlib,R和gnuplot,但他们似乎无法绘制这种情节.R的第三方ade4包似乎可以绘制它,但我不确定我是否可以在同一个三角形上绘制多个图.
我需要在Linux或Windows下运行的东西.我愿意接受任何建议,包括其他语言的库,例如Perl,PHP,Ruby,C#和Java.
创建了一个非常基本的脚本,用于生成三元(或更多)图.没有网格线或刻度线,但使用"基础"数组中的向量添加不会太难.
from pylab import * def ternaryPlot( data, # Scale data for ternary plot (i.e. a + b + c = 1) scaling=True, # Direction of first vertex. start_angle=90, # Orient labels perpendicular to vertices. rotate_labels=True, # Labels for vertices. labels=('one','two','three'), # Can accomodate more than 3 dimensions if desired. sides=3, # Offset for label from vertex (percent of distance from origin). label_offset=0.10, # Any matplotlib keyword args for plots. edge_args={'color':'black','linewidth':2}, # Any matplotlib keyword args for figures. fig_args = {'figsize':(8,8),'facecolor':'white','edgecolor':'white'}, ): ''' This will create a basic "ternary" plot (or quaternary, etc.) ''' basis = array( [ [ cos(2*_*pi/sides + start_angle*pi/180), sin(2*_*pi/sides + start_angle*pi/180) ] for _ in range(sides) ] ) # If data is Nxsides, newdata is Nx2. if scaling: # Scales data for you. newdata = dot((data.T / data.sum(-1)).T,basis) else: # Assumes data already sums to 1. newdata = dot(data,basis) fig = figure(**fig_args) ax = fig.add_subplot(111) for i,l in enumerate(labels): if i >= sides: break x = basis[i,0] y = basis[i,1] if rotate_labels: angle = 180*arctan(y/x)/pi + 90 if angle > 90 and angle <= 270: angle = mod(angle + 180,360) else: angle = 0 ax.text( x*(1 + label_offset), y*(1 + label_offset), l, horizontalalignment='center', verticalalignment='center', rotation=angle ) # Clear normal matplotlib axes graphics. ax.set_xticks(()) ax.set_yticks(()) ax.set_frame_on(False) # Plot border ax.plot( [basis[_,0] for _ in range(sides) + [0,]], [basis[_,1] for _ in range(sides) + [0,]], **edge_args ) return newdata,ax if __name__ == '__main__': k = 0.5 s = 1000 data = vstack(( array([k,0,0]) + rand(s,3), array([0,k,0]) + rand(s,3), array([0,0,k]) + rand(s,3) )) color = array([[1,0,0]]*s + [[0,1,0]]*s + [[0,0,1]]*s) newdata,ax = ternaryPlot(data) ax.scatter( newdata[:,0], newdata[:,1], s=2, alpha=0.5, color=color ) show()
R有一个名为VCD的外部包,可以做你想要的.
文档非常好(122页手册分发包装); 该软件包的作者(Michael Friendly教授)也有一本名为Visual Display of Quantitative Information的同名书.
要使用vcd创建三元图,只需调用ternaryplot()并传入mx 3矩阵,即具有三列的矩阵.
方法签名非常简单; 只需要一个参数(mx 3数据矩阵); 并且所有关键字参数都与绘图的美学有关,除了缩放,当设置为1时,逐列规范化数据.
为了在三元图上绘制数据点,给定点的坐标计算为质点的重心,其中包含数据矩阵的每个特征值是单独的权重,因此点V的坐标(a,b, c)是
V(b, c/2, c * (3^.5)/2
为了生成下面的图表,我刚刚创建了一些假数据来表示四种不同的化学混合物,每种化学混合物由三种物质(x,y,z)的不同部分组成.我缩放了输入(所以x + y + z = 1)但是如果你为它的'scale'参数传递一个值,函数会为你做的(实际上,默认值是1,我相信这就是你的问题需要).我使用不同的颜色和符号来表示四个数据点,但您也可以使用单个颜色/符号并标记每个点(通过'id'参数).
http://www.freeimagehosting.net/uploads/35393eaba5.png
我在R中创作的一个包刚刚被CRAN接受,网页是www.ggtern.com:
它基于ggplot2,我用它作为平台.对我来说,驱动力是一种在工作中保持一致的愿望,而且,由于我大量使用ggplot2,因此开发包是一个合乎逻辑的进展.
对于那些使用ggplot2的人来说,使用ggtern应该是轻而易举的,这里有几个可以实现的示范.
使用以下代码生成:
# Load data data(Feldspar) # Sort it by decreasing pressure # (so small grobs sit on top of large grobs Feldspar <- Feldspar[with(Feldspar, order(-P.Gpa)), ] # Build and Render the Plot ggtern(data = Feldspar, aes(x = An, y = Ab, z = Or)) + #the layer geom_point(aes(fill = T.C, size = P.Gpa, shape = Feldspar)) + #scales scale_shape_manual(values = c(21, 24)) + scale_size_continuous(range = c(2.5, 7.5)) + scale_fill_gradient(low = "green", high = "red") + #theme tweaks theme_tern_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1), legend.box.just = "left") + #tweak guides guides(shape= guide_legend(order =1, override.aes=list(size=5)), size = guide_legend(order =2), fill = guide_colourbar(order=3)) + #labels and title labs(size = "Pressure/GPa", fill = "Temperature/C") + ggtitle("Feldspar - Elkins and Grove 1990")
轮廓图也针对三元环境进行了修补,并且包含了一个新的几何图形,用于通过Mahalanobis距离表示置信区间.
使用以下代码生成:
ggtern(data=Feldspar,aes(An,Ab,Or)) + geom_confidence(aes(group=Feldspar, fill=..level.., alpha=1-..level..), n=2000, breaks=c(0.01,0.02,0.03,0.04, seq(0.05,0.95,by=0.1), 0.99,0.995,0.9995), color=NA,linetype=1) + geom_density2d(aes(color=..level..)) + geom_point(fill="white",aes(shape=Feldspar),size=5) + theme_tern_bw() + theme_tern_nogrid() + theme(ternary.options=element_ternary(padding=0.2), legend.position=c(0,1), legend.justification=c(0,1), legend.box.just="left") + labs(color="Density",fill="Confidence", title="Feldspar - Elkins and Grove 1990 + Confidence Levels + Density") + scale_color_gradient(low="gray",high="magenta") + scale_fill_gradient2(low="red",mid="orange",high="green", midpoint=0.8) + scale_shape_manual(values=c(21,24)) + guides(shape= guide_legend(order =1, override.aes=list(size=5)), size = guide_legend(order =2), fill = guide_colourbar(order=3), color= guide_colourbar(order=4), alpha= "none")