在尝试使用 matplotlib 和plotly 创建雷达图时,我一直在尝试找出一种方法来计算图表上所示的每个数据集的面积。与我通过分配“分数”分配的变量相比,这将帮助我全面评估数据集的有效性,“分数”相当于雷达图的面积。
例如,在下图中,雷达图上绘制了两个数据集,每个数据集代表根据轴中的标准/特征评估的不同对象。我想计算多边形覆盖的总面积,为每个区域分配一个“总分”,作为另一个指标。
有人知道该怎么做吗?
# 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 |
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 |
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}"))
罗布的解决方案看起来令人难以置信,但它不再有效:(