通过整数(计数器)从颜色图中迭代颜色
Posted
技术标签:
【中文标题】通过整数(计数器)从颜色图中迭代颜色【英文标题】:Iterate color from colormap by integer (counter) 【发布时间】:2022-01-13 08:49:31 【问题描述】:我尝试通过整数从颜色图中获取颜色,就像从列表中获取值一样:
list[1]
我想使用的颜色图可以在此处的“定性('tab20')”下找到:
https://matplotlib.org/stable/tutorials/colors/colormaps.html
我的代码简化了:
import plotly.graph_objs as go
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn')
df = pd.DataFrame(np.random.randint(0,100,size=(100, 5)), columns=list('ABCDF'))
count=1
fig = go.Figure()
for i in df.columns:
fig.add_trace(go.Scatter(x=df['A'], y=df[i], line_color=plt.plot_color_gradients['Qualitative']['tab20'][count]))
count+=1
fig.show()
这部分是上面示例的伪代码和我的核心问题,我不知道如何正确实现颜色图以及如何通过整数访问其中的颜色:
line_color=plt.plot_color_gradients['Qualitative']['tab20'][count]
我希望每条轨迹都能通过整数(计数)从颜色图中获得漂亮的颜色,并且颜色的给出顺序是可复制的。跟踪的数量是可变的,但很可能永远不会超过 20。
【问题讨论】:
代码的当前(错误)行为是什么? 伪代码行。我不知道如何正确实现颜色图以及如何通过整数访问其中的颜色。 【参考方案1】:将fig.for_each_trace()
与count()
一起从itertools
使用,您可以将其缩小为:
col_list = px.colors.qualitative.Alphabet*10
counter = count(start = 0, step = 1)
fig = px.line(df, x=df.index, y=df.columns, template = 'plotly_dark')
fig.for_each_trace(lambda t: t.update(line_color = col_list[next(counter)]))
情节
一个潜在的缺点是您可能会在用完痕迹之前用完颜色。解决这个问题的一个hacky方法是让列表重复多次:
col_list = px.colors.qualitative.Alphabet*10
或者您可以使用itertools
和cycle()
中的另一种方法,如下所示:
col_cycle = cycle(px.colors.qualitative.Alphabet)
fig = px.line(df, x=df.index, y=df.columns, template = 'plotly_dark')
fig.for_each_trace(lambda t: t.update(line_color = next(col_cycle)))
count()
的完整代码
import pandas as pd
import numpy as np
import plotly.express as px
from itertools import cycle
from itertools import count
# data
np.random.seed(1)
df = pd.DataFrame(np.random.randint(-1,2,size=(100, 5)), columns=list('ABCDF'))
df.iloc[0] = 0
df = df.cumsum()
col_list = px.colors.qualitative.Alphabet*10
counter = count(start = 0, step = 1)
# figure
fig = px.line(df, x=df.index, y=df.columns, template = 'plotly_dark')
fig.for_each_trace(lambda t: t.update(line_color = col_list[next(counter)]))
fig.show()
cycle()
的完整代码
import pandas as pd
import numpy as np
import plotly.express as px
from itertools import cycle
from itertools import count
# data
np.random.seed(1)
df = pd.DataFrame(np.random.randint(-1,2,size=(100, 5)), columns=list('ABCDF'))
df.iloc[0] = 0
df = df.cumsum()
# color cycle and figure
col_cycle = cycle(px.colors.qualitative.Alphabet)
fig = px.line(df, x=df.index, y=df.columns, template = 'plotly_dark')
fig.for_each_trace(lambda t: t.update(line_color = next(col_cycle)))
fig.show()
【讨论】:
谢谢。循环提示非常有用。 请问,使用 plotly.express 还是 plotly.graph_objs 更好? @Veritas_in_Numeris 这在一定程度上取决于您想要做什么。两者都非常有用且用途广泛。大多数时候,我使用px
构建图形结构,并使用fig.add_traces(go.Scatter())
添加元素。您应该知道的一件事是,这两种方法都创建了相同的绘图对象。【参考方案2】:
如果您要使用的颜色图是在matplotlib中设置的tab20,请将其从matplotlib的颜色图转换为十六进制代码并将其存储在列表中。使用该颜色列表并将其用于循环过程的计数器。另外,plotly 有 seaborn 的风格,所以我指定了。 plotly 的颜色图类似于 tab20,所以 plotly 可能就是你所需要的。更多信息请参见information。
import pandas as pd
import numpy as np
import plotly.graph_objs as go
import matplotlib.pyplot as plt
import matplotlib.colors as cm
df = pd.DataFrame(np.random.randint(0, 100, size=(100, 5)), columns=list('ABCDF'))
colors = [cm.to_hex(plt.cm.tab20(i)) for i in range(20)]
fig = go.Figure()
for i,c in enumerate(df.columns):
fig.add_trace(go.Scatter(
x=df.index,
y=df[c],
mode='lines',
marker=dict(color=colors[i])
))
fig.update_layout(template='seaborn')
fig.show()
【讨论】:
这是完美的。非常精简和性感的解决方案。谢谢以上是关于通过整数(计数器)从颜色图中迭代颜色的主要内容,如果未能解决你的问题,请参考以下文章