Matplotlib Colormaps – 为每个图形/线条/主题选择不同的颜色

Posted

技术标签:

【中文标题】Matplotlib Colormaps – 为每个图形/线条/主题选择不同的颜色【英文标题】:Matplotlib Colormaps – Choosing a different color for each graph/line/subject 【发布时间】:2022-01-05 14:37:48 【问题描述】:

我创建了一个脚本来读取和绘制 .txt 文件及其内容(数字/值)。每个 .txt 文件位于不同的文件夹中。每个文件夹依次代表数据源自的一个主题。

此代码运行良好。 Python 读取每个单独的 .txt。文件并将 23 个单独的图形/线绘制成一个图形。 Python 在这里使用了一些标准颜色,即每张图都自动以不同的颜色呈现。

我想做的是:我不想使用 python 自动分配的标准颜色而不添加任何与颜色相关的代码,而是使用 matplotlib 中的特定颜色图(例如“等离子”)。

问题:无论我使用来自互联网的什么代码,所有图形/线条/主题总是收到相同的颜色(例如,等离子颜色图中的第一种颜色或最后一种颜色)。

如何指定代码以使每一行都从选择的颜色图中获得一种不同的颜色?

这是我的代码:

# Initialize
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from matplotlib.pyplot import cm

# Numpy.loadtxt – Loads data from a textfile. Scipy.signal.welch – Creation of the FFT/power-spectrum. f, Pxx_den creates the ideal frequencies/FFT (f, Welch = Power Spectrum or Power Spectral Density)
Subjects = ["Subject1", "Subject2", "Subject3", "Subject4", "Subject5", "Subject7", "Subject8", "Subject9", "Subject10", "Subject11", "Subject12", "Subject13",
            "Subject14", "Subject15", "Subject16", "Subject17", "Subject18", "Subject19", "Subject20", "Subject22", "Subject23", "Subject24", "Subject25"]

for Subject in Subjects:

    Subject = np.loadtxt("/volumes/SanDisk2/fmri/dataset/processed/extracted_timeseriespython/restingstate/0/TimeSeries.SPC.Core_ROI.0.txt".format(Subject), comments="#", delimiter=None,
                         converters=None, skiprows=0, usecols=0, unpack=False, ndmin=0, encoding=None, max_rows=None, like=None)

    f, Welch = signal.welch(Subject, fs=1.0, window="hann", nperseg=None, noverlap=None, nfft=1024, detrend="constant", return_onesided=True, scaling="density", axis=-1, average="mean")

    cmap = plt.get_cmap("inferno")
    slicedCM = cmap(np.linspace(0, 1, len(Subjects)))

    plt.plot(f, Welch, c=slicedCM[Subjects.index(Subject)]) 
    

# Grid labels
plt.title("Power Spectrum for all subjects", fontsize=12, fontweight="bold")
plt.xlabel("Log Frequency [Hz]", fontsize=11, fontweight="bold")
plt.ylabel("Log Power [Hz]", fontsize=11, fontweight="bold")

# Grid dimenions and style
plt.xlim([0.005, 0.2]) # x-axis range
plt.ylim([0, 100]) # y-axis range

plt.xticks(np.arange(0, 0.21, 0.025)) # x ticks range (start, end, step)
plt.yticks(np.arange(0, 101, 10)) # y ticks range (start, end, step)

plt.grid(True) # Show grid
plt.rc("axes", axisbelow=True) # Grid behind figures
plt.rc("grid", linestyle="-", color="black") # Grid look

# Show result
plt.show()

这是生成的屏幕截图,显示使用标准颜色而不是所需的等离子颜色图:

我正在运行 matplotlib 3.5.0MacOSX 作为后端。

【问题讨论】:

嗨 Johan,结果是 3.5.0 和 MacOSX。我附上了一个截图来更好地解释这个问题。屏幕截图显示了 python/matplotlib 使用的标准颜色设置。我需要的是每条线都有一种颜色,就像这里显示的那样,但是来自特定的颜色图。 abload.de/img/screenshot2021-11-28acnjbw.png 您能否edit 您的帖子并尝试使您的代码易于重现,例如类似于my test code and plot? 我不明白你为什么要绘制同样的东西 23 次。也许只绘制一次。 【参考方案1】:

实现目标的一种方法是分割颜色图,然后用其中一种颜色绘制每条线。请参阅下面可以在适当位置集成到您的代码中的行。

import numpy as np
import matplotlib.pyplot as plt

# 1. Choose your desired colormap
cmap = plt.get_cmap('plasma')

# 2. Segmenting the whole range (from 0 to 1) of the color map into multiple segments
slicedCM = cmap(np.linspace(0, 1, len(Subjects))) 

# 3. Color the i-th line with the i-th color, i.e. slicedCM[i]
plt.plot(f, Welch, c=slicedCM[Subjects.index(Subject)]) 

(前两行可以放在开头,您可以将代码中的线绘制曲线替换为上面建议的第三行代码。)

或者,也许是一种更简洁的方法,通过Subjects在主循环中使用以下行:

cmap = plt.get_cmap('inferno')
plt.plot(f, Welch, c=cmap(Subjects.index(Subject)/len(Subjects))) 

(我在您的问题中看到,当您再次将文件加载到 Subject 时,您正在更改 Subject。只需使用另一个变量名,例如,data = np.loadtxt...,然后是 f, Welch = signal.welch(data, ....。保留用于绘图的代码上面建议的不同颜色,你不会有任何问题。)

【讨论】:

您的代码运行良好。但结果与我尝试的所有其他代码相同:颜色图中只有一种颜色用于所有图形。更准确地说,当我在“for i in range(23):”中使用值 23 时,将使用颜色图等离子的最后一种颜色(黄色)。当我将此值更改为 1 时,将使用颜色图中的第一个值(深紫色)。我觉得一旦通过 "Subject=np.loadtxt("/volumes/San..." 或 "f, Welch=signal.welch(Subject, fs= 1.0 ..." 行。问题出在此处吗?我对 P 还是完全陌生。 好吧,我想我现在才开始理解真正的问题。看起来像“f”和“Welch”二维数组或矩阵或列表列表或......所以你为每个“i”绘制多条线,你希望它们有不同的颜色,对吗?跨度> 您好,感谢您的帮助。每一行都来自一个不同的 .txt 文件。 Python 理解这一点,因为默认情况下它会用不同的颜色为每一行着色(根本不添加任何与颜色相关的代码)。一旦我们添加了颜色代码,例如,使用颜色图,Python 就会以某种方式为所有行应用相同的颜色。这就是问题。例如,上面 Johan 显示的代码可以正常工作。由于我的 Python 版本或计算机,这不是错误或问题,但问题与代码有关。我们需要告诉 Python 为每一行使用一种新颜色,但要使用特定的颜色图。 对不起,我还是有点困惑。您在代码中绘制了 23 次相同的东西。你会检查是不是这个问题?我编辑了我的答案以解决可能出现的问题;检查并让我知道这是否有帮助。我分别绘制了存储在“f”和“Welch”中的每条曲线,并对它们进行了颜色编码。 我没有画同样的东西 23 次。我根据 23 个主题绘制了 23 个图表。每个主题都是具有不同数值的不同 txt 文件。这就是为什么在我上面显示的屏幕截图中,每个图表都有不同的颜色和形状。如果我将相同的图表绘制 23 次,则该图将仅显示 1 种颜色的 1 条单线,而不是 23 种颜色的 23 条线。对于更新代码的最后一行(“plt.plot(f[i, :], Welch[i, :], c=slicedCM[i])”),我收到以下错误:“IndexError: too many indices for数组:数组是一维的,但有 2 个被索引”。我会尝试调整你的代码。【参考方案2】:

您想为颜色图实例提供一个介于 0 和 1 之间的参数,这需要最少的计划,例如,

x = np.linspace(0,355/113, 101)
p = plt.get_cmap('plasma')
n = 23
for i in range(n):
    plt.plot(x, np.sin(x-i/2/n), color=p(i/(n-1)))

【讨论】:

我很想删除我的答案,但我有点喜欢我得到的彩色拱门......【参考方案3】:

我的 CMasher 有函数 take_cmap_colors() (https://cmasher.readthedocs.io/user/usage.html#taking-colormap-colors),它是为处理这种情况而编写的。 只需向它提供一个颜色图、颜色数量以及您想要的可选范围,它就会返回一个颜色列表(采用 MPL 可以理解的格式),这些颜色是从所提供的颜色图中统一获取的。

因此,在您的特定情况下,您可以这样做:

# Import CMasher
import cmasher as cmr

# Obtain colors from a colormap
colors = cmr.take_cmap_colors('inferno', len(Subjects))

# YOUR FOR-LOOP
for Subject, color in zip(Subjects, colors):

    Subject = np.loadtxt("/volumes/SanDisk2/fmri/dataset/processed/extracted_timeseriespython/restingstate/0/TimeSeries.SPC.Core_ROI.0.txt".format(Subject), comments="#", delimiter=None,
                         converters=None, skiprows=0, usecols=0, unpack=False, ndmin=0, encoding=None, max_rows=None, like=None)

    f, Welch = signal.welch(Subject, fs=1.0, window="hann", nperseg=None, noverlap=None, nfft=1024, detrend="constant", return_onesided=True, scaling="density", axis=-1, average="mean")

    plt.plot(f, Welch, c=color)

您可以为函数提供 MPL 中任何已注册颜色图的名称,如果您使用自定义的未注册颜色图,则可以提供 Colormap 对象。

还可以查看 CMasher 提供给您的颜色图 (https://cmasher.readthedocs.io/user/introduction.html)。 您可能会在其中找到更适合您的情节的候选人。

【讨论】:

以上是关于Matplotlib Colormaps – 为每个图形/线条/主题选择不同的颜色的主要内容,如果未能解决你的问题,请参考以下文章

Matplotlib Colormaps – 为每个图形/线条/主题选择不同的颜色

matplotlib 可视化 —— cmap(colormap)

Matplotlib 散点图和颜色图的问题

Python使用matplotlib函数subplot可视化多个不同颜色的折线图为每一个子图添加子图小标题(subtitle)

Python使用matplotlib函数subplot可视化多个不同颜色的折线图为每一个子图添加子图小标题(subtitle)使用family参数自定义子标题字体类型字体大小

colormap中的内嵌彩色模块和调用方式