Plotly:如何为每个变量创建具有不同样式和颜色的线图?
Plotly: How to create a line plot with different style and color for each variable?
我正在尝试使用 Plotly Express 创建一个包含 10 条不同颜色和标记的不同线条的图表。类似于此:
我可以按照文档中的建议使用 px.line
函数创建具有不同颜色的漂亮图表。我的代码如下所示:
import plotly.express as px
import numpy as np
import pandas as pd
rand_elems = []
for i in range(10):
rand_elems.append(np.random.randn(25))
data = pd.DataFrame(rand_elems)
px.line(data_frame=data.T)
我的折线图是这样的:
其中每个变量都是一个 (25,) numpy 数组,其中包含来自标准正态分布的随机值(使用 np.random.randn(25)
创建)。
有什么方法可以为每一行添加不同的样式吗?也欢迎使用其他绘图库,因为我在 Plotly 的文档中找不到解决方案。
我知道我可以使用的线条样式有限制。也许我可以循环浏览它们和颜色?对此有什么好的解决方案?
编辑:图表的目的仅仅是为了表明信号是随机的并且在标准正态分布范围内。
我知道的方法是为要绘制的每条线创建单独的图形对象(每条线都有自己的样式)。然后创建所有图形对象的列表并将其传递给 go.Figure() 函数的 data
参数。
有关示例,请参阅 this blog。
px.line
非常适合高度多样化的数据集,例如跨越几大洲的一系列国家/地区的不同类别,因为您可以使用 color = 'country
、line_dash = 'continent
等参数来区分类别为它们分配颜色和形状。这是一个使用内置数据集 px.data.gapminder()
子集的示例
情节 1
代码 1
import plotly.express as px
from plotly.validators.scatter.marker import SymbolValidator
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
fig.show()
但您似乎也对标记的不同 形状 感兴趣,而且对于那些易于使用的标记,似乎没有内置功能如 color
和 line_shape
。因此,接下来是一种循环使用可用标记形状并将其应用于不同国家(例如)的方法。您当然可以通过从 marker styles 中选择形状来定义自己的序列,例如:
['arrow-bar-left', 'asterisk', 'arrow-right', 'line-ne', 'circle-cross', 'y-left']
但您也可以根据 raw_symbols = SymbolValidator().values
获取大量样式,稍微改进这些发现并将其添加到国家/地区名称等内容中。
这是结果
这是您的操作方式:
import plotly.express as px
from itertools import cycle
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
# retrieve a bunch of markers
raw_symbols = SymbolValidator().values
namestems = []
namevariants = []
symbols = []
for i in range(0,len(raw_symbols),3):
name = raw_symbols[i+2]
symbols.append(raw_symbols[i])
namestems.append(name.replace("-open", "").replace("-dot", ""))
namevariants.append(name[len(namestems[-1]):])
markers = cycle(list(set(namestems)))
# set unique marker style for different countries
fig.update_traces(mode='lines+markers')
for d in fig.data:
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
我已经采用了@vestland 的代码并改编并修复了一个更简单的版本,它完全满足了我的需要。
这个想法是使用 plotly.validators.scatter.marker
中的 SymbolValidator()
,如@vestland 的回答中所述。还可以在此列表中添加一个随机因素以获得更不同的结果。
示例运行代码:
import plotly.express as px
from itertools import cycle
from plotly.validators.scatter.marker import SymbolValidator
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
raw_symbols = SymbolValidator().values
# Take only the string values which are in this order.
symbols_names = raw_symbols[::-2]
markers = cycle(symbols_names)
# set unique marker style for different countries
fig.update_traces(mode='lines+markers')
for d in fig.data:
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
此代码生成下图:
非常感谢@vestland 的见解我想知道 Plotly 是否可以在下一个版本中将其作为参数选项。
更新:
如果您的 DataFrame 没有像我的那样用于 line_dash
参数的聚合列,您也可以循环浏览具有线条样式的列表并使用 `fig.data.line["dash 覆盖它们"] 如下所示:
- 生成数据和导入包的代码。
import numpy as np
import random
import plotly.express as px
import numpy as np
import pandas as pd
from itertools import cycle
from random import shuffle
from plotly.validators.scatter.marker import SymbolValidator
from plotly.validators.scatter.line import DashValidator
rand_elems = []
for i in range(10):
rand_elems.append(np.random.randn(25))
data = pd.DataFrame(rand_elems)
data.index = [f"Signal {i}" for i in range(10)]
- 为 DataFrame 中的每一列生成不同标记和线条样式的代码。
line_styles_names = ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
line_styles = cycle(line_styles_names)
fig = (px.line(data_frame=data.T,
color_discrete_sequence=px.colors.qualitative.Bold_r,
title="First 10 Signals Visualization",
))
symbols_names = list(set([i.replace("-open", "").replace("-dot", "") for i in SymbolValidator().values[::-2]]))
shuffle(symbols_names)
markers = cycle(symbols_names)
_ = fig.update_traces(mode='lines+markers')
for d in fig.data:
d.line["dash"] = next(line_styles)
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
有了这个,结果应该类似于这个,这正是我想要的。
我正在尝试使用 Plotly Express 创建一个包含 10 条不同颜色和标记的不同线条的图表。类似于此:
我可以按照文档中的建议使用 px.line
函数创建具有不同颜色的漂亮图表。我的代码如下所示:
import plotly.express as px
import numpy as np
import pandas as pd
rand_elems = []
for i in range(10):
rand_elems.append(np.random.randn(25))
data = pd.DataFrame(rand_elems)
px.line(data_frame=data.T)
我的折线图是这样的:
其中每个变量都是一个 (25,) numpy 数组,其中包含来自标准正态分布的随机值(使用 np.random.randn(25)
创建)。
有什么方法可以为每一行添加不同的样式吗?也欢迎使用其他绘图库,因为我在 Plotly 的文档中找不到解决方案。
我知道我可以使用的线条样式有限制。也许我可以循环浏览它们和颜色?对此有什么好的解决方案?
编辑:图表的目的仅仅是为了表明信号是随机的并且在标准正态分布范围内。
我知道的方法是为要绘制的每条线创建单独的图形对象(每条线都有自己的样式)。然后创建所有图形对象的列表并将其传递给 go.Figure() 函数的 data
参数。
有关示例,请参阅 this blog。
px.line
非常适合高度多样化的数据集,例如跨越几大洲的一系列国家/地区的不同类别,因为您可以使用 color = 'country
、line_dash = 'continent
等参数来区分类别为它们分配颜色和形状。这是一个使用内置数据集 px.data.gapminder()
情节 1
代码 1
import plotly.express as px
from plotly.validators.scatter.marker import SymbolValidator
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
fig.show()
但您似乎也对标记的不同 形状 感兴趣,而且对于那些易于使用的标记,似乎没有内置功能如 color
和 line_shape
。因此,接下来是一种循环使用可用标记形状并将其应用于不同国家(例如)的方法。您当然可以通过从 marker styles 中选择形状来定义自己的序列,例如:
['arrow-bar-left', 'asterisk', 'arrow-right', 'line-ne', 'circle-cross', 'y-left']
但您也可以根据 raw_symbols = SymbolValidator().values
获取大量样式,稍微改进这些发现并将其添加到国家/地区名称等内容中。
这是结果
这是您的操作方式:
import plotly.express as px
from itertools import cycle
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
# retrieve a bunch of markers
raw_symbols = SymbolValidator().values
namestems = []
namevariants = []
symbols = []
for i in range(0,len(raw_symbols),3):
name = raw_symbols[i+2]
symbols.append(raw_symbols[i])
namestems.append(name.replace("-open", "").replace("-dot", ""))
namevariants.append(name[len(namestems[-1]):])
markers = cycle(list(set(namestems)))
# set unique marker style for different countries
fig.update_traces(mode='lines+markers')
for d in fig.data:
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
我已经采用了@vestland 的代码并改编并修复了一个更简单的版本,它完全满足了我的需要。
这个想法是使用 plotly.validators.scatter.marker
中的 SymbolValidator()
,如@vestland 的回答中所述。还可以在此列表中添加一个随机因素以获得更不同的结果。
示例运行代码:
import plotly.express as px
from itertools import cycle
from plotly.validators.scatter.marker import SymbolValidator
# data
df = px.data.gapminder()
df = df[df['country'].isin(['Canada', 'USA', 'Norway', 'Sweden', 'Germany'])]
# plotly
fig = px.line(df, x='year', y='lifeExp',
color='country',
line_dash = 'continent')
raw_symbols = SymbolValidator().values
# Take only the string values which are in this order.
symbols_names = raw_symbols[::-2]
markers = cycle(symbols_names)
# set unique marker style for different countries
fig.update_traces(mode='lines+markers')
for d in fig.data:
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
此代码生成下图:
更新:
如果您的 DataFrame 没有像我的那样用于 line_dash
参数的聚合列,您也可以循环浏览具有线条样式的列表并使用 `fig.data.line["dash 覆盖它们"] 如下所示:
- 生成数据和导入包的代码。
import numpy as np
import random
import plotly.express as px
import numpy as np
import pandas as pd
from itertools import cycle
from random import shuffle
from plotly.validators.scatter.marker import SymbolValidator
from plotly.validators.scatter.line import DashValidator
rand_elems = []
for i in range(10):
rand_elems.append(np.random.randn(25))
data = pd.DataFrame(rand_elems)
data.index = [f"Signal {i}" for i in range(10)]
- 为 DataFrame 中的每一列生成不同标记和线条样式的代码。
line_styles_names = ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
line_styles = cycle(line_styles_names)
fig = (px.line(data_frame=data.T,
color_discrete_sequence=px.colors.qualitative.Bold_r,
title="First 10 Signals Visualization",
))
symbols_names = list(set([i.replace("-open", "").replace("-dot", "") for i in SymbolValidator().values[::-2]]))
shuffle(symbols_names)
markers = cycle(symbols_names)
_ = fig.update_traces(mode='lines+markers')
for d in fig.data:
d.line["dash"] = next(line_styles)
d.marker.symbol = next(markers)
d.marker.size = 10
fig.show()
有了这个,结果应该类似于这个,这正是我想要的。