python 用于绘制三元/三角形图的库/工具

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/701429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:40:58  来源:igfitidea点击:

Library/tool for drawing ternary/triangle plots

pythonrplotgnuplot

提问by Cristian Ciupitu

I need to draw ternary/triangle plotsrepresenting mole fractions (x, y, z) of various substances/mixtures (x+ y+ z= 1). Each plot represents iso-valued substances, e.g. substances which have the same melting point. The plots need to be drawn on the same triangle with different colors/symbols and it would be nice if I could also connect the dots.

我需要绘制表示各种物质/混合物 ( x+ y+ z= 1) 的摩尔分数 ( x, y, z) 的三元/三角形图。每幅图代表等值物质,例如具有相同熔点的物质。这些图需要用不同的颜色/符号绘制在同一个三角形上,如果我也可以连接点就好了。

I have looked at matplotlib, R and gnuplot, but they don't seem to be able to draw this kind of plot. The 3rd party ade4package for R seems to be able to draw it, but I'm not sure if I can draw multiple plots on the same triangle.

我看过 matplotlib、R 和 gnuplot,但他们似乎无法绘制这种情节。R的第 3 方ade4包似乎能够绘制它,但我不确定是否可以在同一个三角形上绘制多个图。

I need something that runs under Linux or Windows. I'm open to any suggestions, including libraries for other languages, e.g. Perl, PHP, Ruby, C# and Java.

我需要在 Linux 或 Windows 下运行的东西。我愿意接受任何建议,包括其他语言的库,例如 Perl、PHP、Ruby、C# 和 Java。

采纳答案by doug

R has an external package called VCDwhich should do what you want.

R 有一个名为VCD的外部包,它应该可以满足您的需求。

The documentation is very good (122 page manual distributed w/ the package); there's also a book by the same name, Visual Display of Quantitative Information, by the package's author (Prof. Michael Friendly).

文档非常好(122 页手册随包分发);还有一本同名的书,定量信息的可视化显示,由包的作者(Michael Friendly 教授)编写。

To create ternary plots using vcd, just call ternaryplot()and pass in an m x 3 matrix, i.e., a matrix with three columns.

要使用vcd创建三元图,只需调用ternaryplot()并传入一个 mx 3 矩阵,即具有三列的矩阵。

The method signature is very simple; only a single parameter (the m x 3 data matrix) is required; and all of the keyword parameters relate to the plot's aesthetics, except for scale, which when set to 1, normalizes the data column-wise.

方法签名非常简单;只需要一个参数(mx 3 数据矩阵);并且所有关键字参数都与绘图的美感有关,但 scale 除外,当设置为 1 时,会按列对数据进行标准化。

To plot data points on the ternary plot, the coordinates for a given point are calculated as the gravity center of mass pointsin which each feature value comprising the data matrix is a separate weight, hence the coordinates of a point V(a, b, c) are

为了在三元图上绘制数据点,给定点的坐标被计算为质点重心,其中包含数据矩阵的每个特征值是一个单独的权重,因此点的坐标 V(a, b, c) 是

V(b, c/2, c * (3^.5)/2

To generate the diagram below, i just created some fake data to represent four different chemical mixtures, each comprised of varying fractions of three substances (x, y, z). I scaled the input (so x + y + z = 1) but the function will do it for you if you pass in a value for its 'scale' parameter (in fact, the default is 1, which i believe is what your question requires). I used different colors & symbols to represent the four data points, but you can also just use a single color/symbol and label each point (via the 'id' argument).

为了生成下图,我刚刚创建了一些假数据来表示四种不同的化学混合物,每种化学混合物由三种物质(x、y、z)的不同比例组成。我缩放了输入(所以 x + y + z = 1)但是如果你为它的 'scale' 参数传入一个值(事实上,默认值是 1,我相信这就是你的问题)需要)。我使用不同的颜色和符号来表示四个数据点,但您也可以只使用一种颜色/符号并标记每个点(通过“id”参数)。

回答by dave

Created a very basic script for generating ternary (or more) plots. No gridlines or ticklines, but those wouldn't be too hard to add using the vectors in the "basis" array.

创建了一个非常基本的脚本来生成三元(或更多)图。没有网格线或刻度线,但使用“基础”数组中的向量添加这些不会太难。

enter image description here

在此处输入图片说明

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()

回答by Nicholas Hamilton

A package I have authored in R has justbeen accepted for CRAN, webpage is www.ggtern.com:

我在 R 中编写的一个包刚刚被 CRAN 接受,网页是www.ggtern.com

It is based off ggplot2, which I have used as a platform. The driving force for me, was a desire to have consistency in my work, and, since I use ggplot2 heavily, development of the package was a logical progression.

它基于ggplot2,我将其用作平台。我的驱动力是希望在我的工作中保持一致性,并且由于我大量使用 ggplot2,因此包的开发是合乎逻辑的。

For those of you who use ggplot2, use of ggtern should be a breeze, and, here is a couple of demonstrations of what can be achieved.

对于那些使用 ggplot2 的人来说,使用 ggtern 应该是轻而易举的,这里有几个可以实现的演示。

Feldspar

长石

Produced with the following code:

使用以下代码生成:

# 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")


Contour plots have also been patched for the ternary environment, and, an inclusion of a new geometry for representing confidence intervals via the Mahalanobis Distance.

还为三元环境修补了等高线图,并且包含了用于通过Mahalanobis 距离表示置信区间的新几何图形。

Contour

轮廓

Produced with the following code:

使用以下代码生成:

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")

回答by xioxox

Veuszsupports ternary plots. Here is an example from the documentation: Example plot

Veusz支持三元图。这是文档中的一个示例:示例图

回答by Frédéric Grosshans

Chlo? Lewis developed a triangle-plot general class, meant to support the soil texture trianglewith Python and Matplotlib. It's available here http://nature.berkeley.edu/~chlewis/Sourcecode.htmlhttps://github.com/chlewissoil/TernaryPlotPy

克洛?Lewis 开发了一个三角图通用类,旨在用 Python 和 Matplotlib支持土壤质地三角形。它可以在这里找到http://nature.berkeley.edu/~chlewis/Sourcecode.html https://github.com/chlewissoil/TernaryPlotPy

Chloe editing to add: Moved it to a more reliable host! Also, it's a public repo, so if you want to request library-ization, you could add an issue. Hope it's useful to someone.

Chloe 编辑添加:将其移至更可靠的主机!此外,它是一个公共存储库,因此如果您想请求图书馆化,您可以添加一个问题。希望它对某人有用。

回答by Phil H

There seems to be an implementation at work herein gnuplot: ternary plot
(source: ugm.ac.id)

似乎是在工作中实现这里在gnuplot的: (来源:ugm.ac.id三元图

回答by Deaton

I just discovered a tool which uses Python/Matplotlib to generate ternary plots called wxTernary. It's available via http://wxternary.sourceforge.net/-- I was able to successfully generate a ternary plot on the first try.

我刚刚发现了一个使用 Python/Matplotlib 生成名为 wxTernary 的三元图的工具。它可以通过http://wxternary.sourceforge.net/ 获得——我第一次尝试就成功地生成了一个三元图。

回答by Eric

There is a R package named soiltexture. It's aimed at soil texture triangle plot, but can be customized for some aspects.

有一个名为soiltexture的 R 包。它针对土壤质地三角形图,但可以针对某些方面进行定制。

回答by CookieOfFortune

Find a vector drawing library and draw it from scratch if you can't find an easier way to do it.

如果找不到更简单的方法,请查找矢量绘图库并从头开始绘制。