如何在plotly/matplotlib中计算雷达图的面积?

问题描述 投票:0回答:2

在尝试使用 matplotlib 和plotly 创建雷达图时,我一直在尝试找出一种方法来计算图表上所示的每个数据集的面积。与我通过分配“分数”分配的变量相比,这将帮助我全面评估数据集的有效性,“分数”相当于雷达图的面积。

例如,在下图中,雷达图上绘制了两个数据集,每个数据集代表根据轴中的标准/特征评估的不同对象。我想计算多边形覆盖的总面积,为每个区域分配一个“总分”,作为另一个指标。

有人知道该怎么做吗?

python matplotlib charts plotly
2个回答
2
投票
  • 已使用多踪迹雷达图示例,如您的图像所示
  • 首先将数据从图中提取回数据框中
    • 以弧度计算 theta,以便可以使用基本三角函数
    • 使用基本三角计算点的xy坐标
# convert theta to be in radians
df["theta_n"] = pd.factorize(df["theta"])[0]
df["theta_radian"] = (df["theta_n"] / (df["theta_n"].max() + 1)) * 2 * np.pi
# work out x,y co-ordinates
df["x"] = np.cos(df["theta_radian"]) * df["r"]
df["y"] = np.sin(df["theta_radian"]) * df["r"]
r θ 踪迹 theta_n theta_弧度 x y
0 1 加工成本 产品A 0 0 1 0
1 5 机械性能 产品A 1 1.25664 1.54508 4.75528
2 2 化学稳定性 产品A 2 2.51327 -1.61803 1.17557
3 2 热稳定性 产品A 3 3.76991 -1.61803 -1.17557
4 3 设备集成 产品A 4 5.02655 0.927051 -2.85317
0 4 加工成本 产品B 0 0 4 0
1 3 机械性能 产品B 1 1.25664 0.927051 2.85317
2 2.5 化学稳定性 产品B 2 2.51327 -2.02254 1.46946
3 1 热稳定性 产品B 3 3.76991 -0.809017 -0.587785
4 2 设备集成 产品B 4 5.02655 0.618034 -1.90211
  • 现在,如果您了解 shapely 的知识,那么从这些点构造多边形就很简单了。从这个多边形
    area
df_a = df.groupby("trace").apply(
    lambda d: shapely.geometry.MultiPoint(list(zip(d["x"], d["y"]))).convex_hull.area
)
踪迹 0
产品A 13.919
产品B 15.2169

完整的MWE

import numpy as np
import pandas as pd
import shapely.geometry
import plotly.graph_objects as go

categories = ['processing cost','mechanical properties','chemical stability',
              'thermal stability', 'device integration']  # fmt: skip

fig = go.Figure()

fig.add_trace(
    go.Scatterpolar(
        r=[1, 5, 2, 2, 3], theta=categories, fill="toself", name="Product A"
    )
)
fig.add_trace(
    go.Scatterpolar(
        r=[4, 3, 2.5, 1, 2], theta=categories, fill="toself", name="Product B"
    )
)

fig.update_layout(
    polar=dict(radialaxis=dict(visible=True, range=[0, 5])),
    # showlegend=False
)

# get data back out of figure
df = pd.concat(
    [
        pd.DataFrame({"r": t.r, "theta": t.theta, "trace": np.full(len(t.r), t.name)})
        for t in fig.data
    ]
)
# convert theta to be in radians
df["theta_n"] = pd.factorize(df["theta"])[0]
df["theta_radian"] = (df["theta_n"] / (df["theta_n"].max() + 1)) * 2 * np.pi
# work out x,y co-ordinates
df["x"] = np.cos(df["theta_radian"]) * df["r"]
df["y"] = np.sin(df["theta_radian"]) * df["r"]

# now generate a polygon from co-ordinates using shapely
# then it's a simple case of getting the area of the polygon
df_a = df.groupby("trace").apply(
    lambda d: shapely.geometry.MultiPoint(list(zip(d["x"], d["y"]))).convex_hull.area
)

# let's use the areas in the name of the traces
fig.for_each_trace(lambda t: t.update(name=f"{t.name} {df_a.loc[t.name]:.1f}"))

输出


0
投票

罗布的解决方案看起来令人难以置信,但它不再有效:(

© www.soinside.com 2019 - 2024. All rights reserved.