Plotly:如何根据类别字符串值为3D散点图定义标记颜色?

5

我正在使用plotly.graph_object进行3D散点图绘制。我想根据类别字符串值定义标记颜色。类别值为A2、A3、A4。如何修改下面的代码?谢谢

这是我所做的:


import plotly.graph_objects as go

x=df_merged_pc['PC1']
y=df_merged_pc['PC2']
z=df_merged_pc['PC3']

color=df_merged_pc['AREA']

fig=go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers',
                                 marker=dict(size=12,
                                             color=df_merged_pc['AREA'],
                                             colorscale ='Viridis'))])
fig.show()

我得到的错误是:

ValueError: 
    Invalid element(s) received for the 'color' property of scatter3d.marker
        Invalid elements include: ['A3', 'A3', 'A3', 'A3', 'A3', 'A3', 'A3', 'A2', 'A2', 'A2']

1
我认为标记的颜色规范必须是颜色名称或数字的数组。为什么不根据数据列指定颜色名称呢? - r-beginners
谢谢r-beginners,我能否使用类别编号列指定颜色名称,就像在seaborn中使用hue参数一样?谢谢。 - roudan
1
格式是数组或列表,所以我认为不可能。如果字典格式是可能的,那么有一种方法,但最简单的方法可能是向数据框添加一个新列,该列包含与类别编号对应的颜色名称。 - r-beginners
谢谢r-beginners。我会尝试。 - roudan
1个回答

6

我可能理解有误,但是我认为你实际上是在询问 plotly.express 的一个广泛使用的内置功能,其中可以为标记数据的子组分配颜色。以 px.data.iris 数据集为例:

fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
              color='species')

在这里,颜色被分配给不同的物种,其中你有三个独特的值['setosa', 'versicolor', 'virginica']

   sepal_length  sepal_width  petal_length  petal_width species  species_id
0           5.1          3.5           1.4          0.2  setosa           1
1           4.9          3.0           1.4          0.2  setosa           1
2           4.7          3.2           1.3          0.2  setosa           1
3           4.6          3.1           1.5          0.2  setosa           1
4           5.0          3.6           1.4          0.2  setosa           1

enter image description here

这个例子可以通过像上面那样更改颜色方案来扩展,此时您的颜色方案可以由一个字典定义:
colors = {"flower": 'green', 'not a flower': 'rgba(50,50,50,0.6)'} 

或者你可以使用以下方式指定离散的颜色序列:

color_discrete_sequence = plotly.colors.sequential.Viridis

你也可以像这样添加一个新的列:random.choice(['花', '不是花']),以更改你想要与颜色相关联的类别。

enter image description here

Plotly.graph_objects

如果你想使用go.Scatter3d,那么我会为每个独特的子组建立一个迹线,并使用itertools.cycle设置颜色,像这样:
colors = cycle(plotly.colors.sequential.Viridis)

fig = go.Figure()
for s in dfi.species.unique():
    df = dfi[dfi.species == s]
    fig.add_trace(go.Scatter3d(x=df['sepal_length'], y = df['sepal_width'], z = df['petal_width'],
                               mode = 'markers',
                               name = s,
                               marker_color = next(colors)))

Plotly Express的完整代码

import plotly.express as px
import random
df = px.data.iris()
colors = {"flower": 'green', 'not a flower': 'rgba(50,50,50,0.6)'}

df['plant'] = [random.choice(['flower', 'not a flower']) for obs in range(0, len(df))]
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
                color = 'plant',
                color_discrete_map=colors
                   )
fig.show()

Plotly图形对象的完整代码

import plotly.graph_objects as go
import plotly
from itertools import cycle

dfi = px.data.iris()
colors = cycle(plotly.colors.sequential.Viridis)

fig = go.Figure()
for s in dfi.species.unique():
    df = dfi[dfi.species == s]
    fig.add_trace(go.Scatter3d(x=df['sepal_length'], y = df['sepal_width'], z = df['petal_width'],
                               mode = 'markers',
                               name = s,
                               marker_color = next(colors)))
fig.show()

非常感谢您,vestland。我很感激您跟进我的问题。是的,如果我使用带有color_discrete_map的plotly express,它可以工作。然而,如果我只使用go.Figure()来使用plotly,它就无法工作。您知道plotly的常规方法吗?谢谢。 - roudan
@roudan 是的。我在原始答案中提供了一个建议。 - vestland
谢谢Vestland。是的,它起作用了。所以根据我对你的代码的理解,我必须使用for循环和add_trace来添加相同类别的点。谢谢。 - roudan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接