【问题标题】:Drawing 3D points on a 2D plot reading values from a file在从文件读取值的 2D 绘图上绘制 3D 点
【发布时间】:2015-05-30 22:37:36
【问题描述】:

我有一个文件,其中包含具有 3 个坐标的点集,由制表符分隔。像这样(为了可读性而添加的空格,原始文件中不存在):

x0 \t y0 \t z0
x0 \t y1 \t z1
x1 \t y0 \t z0
x1 \t y1 \t z1
x1 \t y2 \t z2
x2 \t y0 \t z0
...

我想在单个 2D 图上将它们绘制为单独的线,例如:

line for all points with x=x0, label=x0
line for all points with x=x1, label=x1
line for all points with x=x2, label=x2

用不同的颜色绘制这些线条。

我知道 numpy 有一个很酷的读取列的功能,如下所示:

my_data = np.genfromtxt(input_file, delimiter='\t', skiprows=0)
Y = my_data[:, 1]
Z = my_data[:, 2]

是否有类似的快速而干净的方法来根据另一列的值来选择列值?

如果没有快速函数(根据旁边的 x 值组成一列),我可以解析文件并逐步构建数据结构。

然后我会做这样的事情,使用 Matplotlib:

ax = plt.axes()
ax.set_xlabel('Y')
ax.set_ylabel('Z')

# for each value of X
    # pick Y and Z values
    plt.plot(Y, Z, linestyle='--', marker='o', color='b', label='x_val')

但我确信有一种更 Pythonic 的方式来做到这一点。也许是列表理解的一些技巧?

编辑:这是完整的工作代码(感谢回答的人)。我只需要一种方法让它显示而不削减传说

import os
import numpy as np
import matplotlib.pyplot as plt

input_file = os.path.normpath('C:/Users/sturaroa/Documents/my_file.tsv')

# read values from file, by column
my_data = np.genfromtxt(input_file, delimiter='\t', skiprows=0)
X = my_data[:, 0]  # 1st column
Y = my_data[:, 1]  # 2nd column
Z = my_data[:, 2]  # 3rd column

# read the unique values in X and use them as keys in a dictionary of line properties
d = {val: {'label': 'x {}'.format(val), 'linestyle': '--', 'marker': 'o'} for val in set(X)}

# draw a different line for each of the unique values in X
for val, kwargs in d.items():
    mask = X == val
    y, z = Y[mask], Z[mask]
    plt.plot(y, z, **kwargs)

# label the axes of the plot
ax = plt.axes()
ax.set_xlabel('Y')
ax.set_ylabel('Z')

# get the labels of all the lines in the graph
handles, labels = ax.get_legend_handles_labels()

# create a legend growing it from the middle and put it on the right side of the graph
lgd = ax.legend(handles, labels, loc='center left', bbox_to_anchor=(1.0, 0.5))

# save the figure so that the legend fits inside it
plt.savefig('my_file.pdf', bbox_extra_artists=(lgd,), bbox_inches='tight')

plt.show()

【问题讨论】:

标签: python numpy matplotlib


【解决方案1】:

假设您有一个包含value:kwargs 对的字典,其中valueX 必须位于该曲线中的值,kwargs 是一个包含要传递给绘图函数的参数的字典。

下面的代码将使用value 构造一个掩码,可用于索引和选择合适的点。

import numpy as np
import matplotlib.pyplot as plt


my_data = np.genfromtxt('data.txt', delimiter=' ', skiprows=0)
X = my_data[:, 0]
Y = my_data[:, 1]
Z = my_data[:, 2]

d = {
    0: {'label': 'x0'},
    1: {'label': 'x1'}
}

for val, kwargs in d.items():
    mask = X == val
    y, z = Y[mask], Z[mask]

    plt.plot(y, z, **kwargs)

plt.legend()

plt.show()

【讨论】:

  • 更好的是,使用dict理解初始化dd = {val: {'label': 'x' + str(val), 'linestyle': '--'} for val in np.unique(X)},然后您可以在后续行中更改每一行的其他属性,例如d[0]['color']='b'd[1]['color']='r'
【解决方案2】:

我建议为此使用字典。首先加载您的数据,

my_data = np.genfromtxt(input_file, delimiter='\t', skiprows=0)
X = my_data[:, 0]
Y = my_data[:, 1]
Z = my_data[:, 2]

然后为每个 x 值创建一个包含数组的字典:

Ydict = {}
Zdict = {}
for x in np.unique(X):
    inds = X == x
    Ydict[x] = Y[inds]
    Zdict[x] = Z[inds]

现在您有两个字典,其键是X 的唯一值(注意np.unique 的使用),字典的值是X 与键匹配的数组。

你的情节调用看起来像,

for x in Ydict:
    plt.plot(Ydict[x], Zdict[x], label=str(x), ...)

您需要将... 替换为您要设置的任何其他行属性,但如果您希望每行具有不同的颜色,请不要使用color='b'

这有帮助吗?

【讨论】:

    猜你喜欢
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2021-04-07
    相关资源
    最近更新 更多