matplotlib 根据动画中的if条件动态更改标记

xesrikrc  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(95)

我有一个要点清单;在我将其转换为数组后,我想用标记'o'显示点,但如果点和移动的点之间的距离大于10,例如,点的标记应该从'o'变为'*'。我尝试这样做,但所有的标记点都改变了,而不仅仅是满足if条件的标记。

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def createList(r1, r2):
    return [item for item in range(r1, r2+1)]

r1, r2 = 1, 50
mialistax=createList(r1, r2)
mialistay=createList(r1, r2)

fig, ax = plt.subplots()

import numpy as np
x_l=np.array(mialistax)
y_l = np.array(mialistay)

def animate(i):

    max_x= max(mialistax)
    max_y=max(mialistay)
    ax.clear()

    if (x_l[i]>10):
        mark='*'
    else:
        mark='o'

    ax.plot(x_l[i],y_l[i],marker=mark)
    ax.set_xlim([0,max_x])
    ax.set_ylim([0,max_y])
    plt.plot(x_l,y_l,marker=mark)

ani = FuncAnimation(fig, animate, frames=200, interval=500, repeat=False)

plt.show()

字符串
在这段代码中,所有点的标记都发生了变化,但我希望标记只对满足if条件的点发生变化。

a11xaf1n

a11xaf1n1#

如果我正确理解了这个问题,您需要一个显示所有点的动画,但是如果索引i处的点(即帧编号)的x值大于10,则该点应转换为"*"标记。
首先,您有三个问题。第一个是你的情节的顺序。

ax.plot(x_l[i], y_l[i], marker=mark)
ax.plot(x_l, y_l, marker=mark)

字符串
这意味着首先绘制单个点,然后在顶部绘制其余点。因此,您将看不到您的“特殊”点,因为它被其他点所掩盖。
第二个问题是,您为两个图(单个点和其余点)设置了相同的标记。我将创建一个包含所有标记的列表,并在满足条件的情况下更新索引为i的标记。然后,遍历所有点并单独绘制它们(因为您无法传递标记列表)。您可能希望突出您的“特殊”点,以便我们可以用不同的颜色显示它。

markers = ["o"]*len(x_l)

def animate(i):
    max_x = max(x_l)
    max_y = max(y_l)
    ax.clear()

    if x_l[i] > 10:
        markers[i] = '*'

    ax.set_xlim([0, max_x])
    ax.set_ylim([0, max_y])
    
    for indx, (x, y, marker) in enumerate(zip(x_l, y_l, markers)):
        color = "tab:orange" if indx == i else "tab:blue"
        ax.plot(x, y, marker=marker, color=color)


最后,你只有50个点,但有frames=200,所以你需要增加你的点或减少帧数来匹配。

ani = FuncAnimation(fig, animate, frames=len(x_l), interval=5, repeat=False)


的数据
我想您是Python的新手,所以我也会提出一些其他的建议来改进您的代码。
1.您可以使用list函数直接从range建立清单:list(range(start, stop))。由于您要将其转换为numpy数组,因此有一个numpy函数可用于此操作:np.arange(start, stop)的数据。
1.对于numpy数组,可以使用max方法:x_l.max(),不过这个变化并不重要。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

plt.close("all")

r1 = 1
r2 = 50
x_l = np.arange(r1, r2+1)
y_l = np.arange(r1, r2+1)

fig, ax = plt.subplots()

markers = ["o"]*x_l.shape[0]

def animate(i):
    max_x = x_l.max()
    max_y = y_l.max()
    ax.cla()
    
    if x_l[i] > 10:
        markers[i] = '*'
    
    for indx, (x, y, marker) in enumerate(zip(x_l, y_l, markers)):
        color = "tab:orange" if indx == i else "tab:blue"
        ax.plot(x, y, marker=marker, color=color)
        
    ax.set_xlim([0, max_x])
    ax.set_ylim([0, max_y])

ani = FuncAnimation(fig, animate, frames=x_l.shape[0], interval=500, repeat=False)
fig.show()

kyvafyod

kyvafyod2#

当你设置frame为一个整数,例如你做了frames=200,那么range(200)将被传递给animate()函数,你的animate(i)参数,被认为是你函数定义中的一个整数,而不是一个range对象。相反,你可以设置一个迭代对象,比如python list或numpy array作为frame参数。请运行下面的代码以了解框架参数的概念:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def createList(r1, r2):
    return [item for item in range(r1, r2+1)]

r1, r2 = 1, 50
mialistax=createList(r1, r2)
mialistay=createList(r1, r2)

fig, ax = plt.subplots()

import numpy as np
x_l=np.array(mialistax)
y_l = np.array(mialistay)

def animate(i):

    max_x= max(mialistax)
    max_y=max(mialistay)
    ax.clear()

    if (x_l[i]>10):
        mark='*'
    else:
        mark='o'

    ax.plot(x_l[i],y_l[i],marker=mark)
    ax.set_xlim([0,max_x])
    ax.set_ylim([0,max_y])
    plt.plot(x_l,y_l,marker=mark)

ani = FuncAnimation(fig, animate, frames=[5,15], interval=500, repeat=True)

plt.show()

字符串

相关问题