Matplotlib:使用镜像或分割x轴的磁滞回线

2024-04-23 08:12:24 发布

您现在位置:Python中文网/ 问答频道 /正文

在实验中,称重传感器以与时间相等的距离增量前进,压缩样本;当到达与起始点的指定距离时停止;然后以等距离增量(随着时间)缩回起始位置。在

y轴上的压力(测压元件读数)与x轴上的压力之间的关系图会产生一个常见的迟滞回线。y轴上的压力(测压元件读数)与x轴上的时间的关系图产生一个不对称峰值,最大压力位于中心,对应于传感器的最大推进点。在

与上述不同,我想绘制y轴上的压力与x轴上的距离,附加的约束是x轴的标签从0开始,最大压力在x轴的中间,0再次在x轴的右端。换言之,曲线的形状与压力v时间曲线图相同,但曲线图的左半部分表示推进过程中探头与起始位置之间的距离;曲线图的右半部分表示缩回时探头与起始位置的距离。在

我的实际数据集包含数千行数据,但为了举例说明,最小的虚拟数据集如下所示,其中3列分别对应于时间、探头与原点的距离和探头测量的压力:

[
[0,0,0],
[1,2,10],
[2,4,30],
[3,6,60],
[4,4,35],
[5,2,15],
[6,0,0]
]

我不知道如何让MatPlotlib构造x轴,使范围从0到最大,然后再回到0。如果你能给我一些建议,让我以最简单优雅的方式完成这一情节,我将不胜感激。非常感谢。在


Tags: 数据距离关系时间传感器中心增量样本
2条回答

如果有时间,可以将其用于x轴值,只需更改x记号标签:

import numpy as np
import matplotlib.pyplot as plt

# Time, Distance, Pressure
data = [[0, 0, 0],
        [1, 2, 10],
        [2, 4, 30],
        [3, 6, 60],
        [4, 4, 35],
        [5, 2, 15],
        [6, 0, 0]]

# convert to array to allow indexing like [i, j]
data = np.array(data)

fig = plt.figure()
ax = fig.add_subplot(111)

max_ticks = 10
skip = (data.shape[0] / max_ticks) + 1
ax.plot(data[:, 0], data[:, 2])  # Pressure(time)
ax.set_xticks(data[::skip, 0])
ax.set_xticklabels(data[::skip, 1])  # Pressure(Distance(time)) ?
ax.set_ylabel('Pressure [Pa?]')
ax.set_xlabel('Distance [m?]')
fig.show()

Pressure as a function of distanceskip只是这样你就不会在图上出现太多的记号,可以随意改变。在

正如在评论中所说,以上仅适用于制服距离随时间的变化。对于非统一的更改,必须使用类似于:

^{pr2}$

enter image description here

关于使用测量值作为刻度会导致这些不是整数的事实,我发现将自动刻度从matplotlib映射到正确的值更容易:

import numpy as np
import matplotlib.pyplot as plt


data = [[0, 0, 0],
        [1, 2, 10],
        [2, 4, 30],
        [3, 6, 60],
        [3.5, 5.4, 40],
        [4, 4, 35],
        [5, 2, 15],
        [6, 0, 0]]
# convert to array to allow indexing like [i, j]
data = np.array(data)


def find_max_pos(data, column=0):
    return np.argmax(data[:, column])


def reverse_unload(data):
    unload_start = find_max_pos(data, 1)
    # prepare new_data with new column:
    new_shape = np.array(data.shape)
    new_shape[1] += 1
    new_data = np.empty(new_shape)
    # copy all correct data
    new_data[:, 0] = data[:, 0]
    new_data[:, 1] = data[:, 1]
    new_data[:, 2] = data[:, 2]
    new_data[:unload_start+1, 3] = data[:unload_start+1, 1]
    # use gradient to fill the rest
    gradient = data[unload_start:-1, 1]-data[unload_start+1:, 1]
    for i, j in enumerate(range(unload_start + 1, data.shape[0])):
        new_data[j, 3] = new_data[j-1, 3] + gradient[i]
    return new_data


def create_map_function(data):
    """
    Return function that maps values of distance
    folded over the maximum pressure applied.
    """
    max_index = find_max_pos(data, 1)
    x0, y0 = data[max_index, 1], data[max_index, 1]
    x1, y1 = 2*data[max_index, 1], 0
    m = (y1 - y0) / (x1 - x0)
    b = y0 - m*x0

    def map_function(x):
        if x < x0:
            return x
        else:
            return m*x+b

    return map_function


def process_data(data):
    data = reverse_unload(data)
    map_function = create_map_function(data)
    fig, ax = plt.subplots()
    ax.plot(data[:, 3], data[:, 2])
    ax.set_xticklabels([map_function(x) for x in ax.get_xticks()])
    ax.grid()
    ax.set_ylabel('Pressure [Pa?]')
    ax.set_xlabel('Distance [m?]')
    fig.show()


if __name__ == '__main__':
    process_data(data)

enter image description here

更新:已经找到了一个解决办法,可以使用np.around函数将小数舍入到最接近的偶数,并指定小数位数(默认值=0):例如,1.5和2.5四舍五入到2.0,-0.5和0.5四舍五入到0.0,等等。更多信息请参阅:https://docs.scipy.org/doc/numpy1.10.4/reference/generated/numpy.around.html

所以berna1111的代码变成:

import numpy as np
import matplotlib.pyplot as plt

# Time, Distance, Pressure
data = [[0, 0, 0],
        [1, 1.9, 10], # Dummy data including decimals to demonstrate rounding
        [2, 4.1, 30],
        [3, 6.1, 60],
        [4, 3.9, 35],
        [5, 1.9, 15],
        [6, -0.2, 0]]

# convert to array to allow indexing like [i, j]
data = np.array(data)

fig = plt.figure()
ax = fig.add_subplot(111)

max_ticks = 10
skip = (data.shape[0] / max_ticks) + 1
ax.plot(data[:, 0], data[:, 2])  # Pressure(time)
ax.set_xticks(data[::skip, 0])
ax.set_xticklabels(np.absolute(np.around((data[::skip, 1]))))  # Pressure(Distance(time)); rounded to nearest integer
ax.set_ylabel('Pressure [Pa?]')
ax.set_xlabel('Distance [m?]')
fig.show()

根据numpy文档,np.around应该将距离的最终值-0.2取整为“0.0”;但是它似乎取整为“-0.0”。不知道为什么会出现这种情况,但是由于在这个特殊情况下,所有的xticklabel都必须是正整数或零,所以我可以使用上面所示的np.absolute函数来纠正这种行为。现在一切似乎都能满足我的要求,但如果我遗漏了什么,或者有更好的解决方案,请告诉我。在

相关问题 更多 >