pyplot中的多色图

时间:2018-04-04 13:44:36

标签: python matplotlib

我确实有以下数据:

  • x_values(单调从大约-300到100上升)
  • y1_values(从0到150随机)
  • y2_values(从-1到1是随机的)
  • colorInfo(可以是0,1,2(蓝色,红色,绿色))

所以:现在我想在x上绘制y1和y2,其中绘图以colorInfo给出的颜色着色

我的数据(我从csv文件中获取)可能如下所示:

tmpSet[8]

所以我希望y1和y2的情节颜色如下:

  • 从-300到-298:蓝色

  • 从-298到-295:蓝色

  • 从-295到-292:红色

现在我有以下代码(基本上是:https://matplotlib.org/1.5.0/examples/pylab_examples/multicolored_line.html的修改版本):

   x   |   y1   |   y2   |   color
 -300  |  50    |   0.5  |     0
 -298  |  51    |   0.4  |     0
 -295  |  51    |   0.2  |     1
 -292  |  44    |   0.1  |     1

最小的csv文件是:

import csv, os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm
import tkinter as tk
from tkinter import filedialog

def plotter(filepath):
    data = read_csv(os.path.abspath(filepath))
    x_values = [None if data["x"] is '' else float(data["x"]) for data["x"] in data["x"]]
    y1_values = [None if data["y1"] is '' else float(data["y1"]) for data["y1"] in data["y1"]]
    y2_values = [None if data["y2"] is '' else float(data["y2"]) for data["y2"] in data["y2"]]
    colorInfo = [None if data["color"] is '' else float(data["color"]) for data["color"] in data["color"]]

    cmap = ListedColormap(['b', 'r', 'g'])
    norm = BoundaryNorm([-1, -0.5, 0.5, 1], cmap.N)


    points = np.array([x_values, y1_values]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)

    lc = LineCollection(segments, cmap=cmap, norm=plt.Normalize(0, 10))
    lc.set_array(colorInfo)
    lc.set_linewidth(3)

    fig1 = plt.figure()
    plt.gca().add_collection(lc)
    plt.show()

def read_csv(filename):
    data = {}
    with open(filename) as csvfile:
        csvreader = csv.DictReader(csvfile, delimiter=',')
        for row in csvreader:
            for key in row.keys():
                if key not in data:
                    data[key] = []
                data[key].append(row[key])
    return data


if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()

    file_path = filedialog.askopenfilename()
    print(file_path)
    plotter(file_path)

这只显示白屏。我想我需要lc.set_array。 但我确实遇到的问题是我只能将其设置为函数而不是我定义的点。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

您看到空白图的原因是因为将LineCollection直接添加到轴不会缩放它,并且默认比例从0到1不包括您的数据。因此,一个立即修复只是在绘图代码末尾的轴上调用autoscale(参见代码中的注释2)。此外,您不需要传递norm参数,因为您的颜色信息已经按要求分类(参见代码中的注释1)。您用来阅读csv的代码似乎在我的测试中有效,但是很奇怪并且会破坏您的列表,因此在调用函数后检查data["x"]只会给出一个值而不是原始列表。

这是一个代码版本,它从包含测试数据的test.csv文件进行绘图。我已经使用pandas而不是csv模块来阅读,因为它更简洁。

import pandas
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap

df = pandas.read_csv('test.csv')

def colorline(x, y, c):
    cmap = ListedColormap(['b', 'r', 'g'])

    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)

    # Note 1: You don't need the norm argument below with your data
    lc = LineCollection(segments, cmap=cmap)
    lc.set_array(c)
    lc.set_linewidth(3)

    return lc

fig, ax = plt.subplots(1, 1)
ax.add_collection(colorline(df.x, df.y1, df.color))
ax.add_collection(colorline(df.x, df.y2, df.color))

# Note 2: Adding the line collections directly doesn't cause autoscaling, so you have to call autoscale manually
ax.autoscale()

上面代码生成的图表如下所示:

enter image description here