设置点与点之间线条数量变化的动画

2024-06-25 05:58:40 发布

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

这个问题与其他动画问题不同,因为我正在尝试为点之间的线交替设置动画。例如,它可能在3分或50分之间。

使用下面的数据框,在Item中标记这些点。前两个时间戳包含4分,但最后两个时间戳的分数降至3分。我试图找到一种有效的方法,将每个时间戳的所有潜在行组合成一个调用函数来设置动画

我遇到的问题是,我正在手动绘制每条线。因此,每个点之间的线目前是硬编码的,这不考虑线数量的变化

我需要的东西,结合了可用的线第一,然后通过这个动画

例如,A, B, C, D是前两个时间点中当前标记的点。但在过去两个时间点,这一数字下降到A, B, C

以下内容不考虑行的交替数量

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import pandas as pd

df1 = pd.DataFrame({
    'Time' : [1,1,1,1,2,2,2,2,3,3,3,4,4,4],  
    'Item' : ['A', 'B', 'C', 'D','A', 'B', 'C', 'D', 'A', 'B', 'C', 'A', 'B', 'C'],
    'GroupA_X' : [3, 4, 5, 1, 2, 5, 6, 2, 1, 6, 7, 2, 7, 8], 
    'GroupA_Y' : [2, 4, 5, 1, 2, 5, 5, 2, 2, 6, 5, 1, 5, 4], 
})

GA_X = np.array(df.groupby('Time')['GroupA_X'].apply(list).tolist())
GA_Y = np.array(df.groupby('Time')['GroupA_Y'].apply(list).tolist())

fig, ax = plt.subplots(figsize = (6,6))
ax.grid(False)
ax.set_xlim(0,10)
ax.set_ylim(0,10)

data = np.stack([GA_X, GA_Y], axis = 2)

vector1 = ax.annotate('', xy = data[0][0], 
            xytext = data[0][1], 
            arrowprops={'arrowstyle': "-", 'color': 'black'}, 
            ha='center')

vector2 = ax.annotate('', xy = data[0][0], 
            xytext = data[0][2], 
            arrowprops={'arrowstyle': "-", 'color': 'black'}, 
            ha='center')

vector3 = ax.annotate('', xy = data[0][1], 
            xytext = data[0][2], 
            arrowprops={'arrowstyle': "-", 'color': 'black'}, 
            ha='center')

def animate(i):
    start1 = np.r_[data[i, 0]]
    end1 = np.r_[data[i, 1]]

    vector1.set_position(start1)
    vector1.xy = end1    

    start2 = np.r_[data[i, 0]]
    end2 = np.r_[data[i, 2]]

    vector2.set_position(start2)
    vector2.xy = end2 

    start3 = np.r_[data[i, 1]]
    end3 = np.r_[data[i, 2]]

    vector3.set_position(start3)
    vector3.xy = end3 

    return 

ani = animation.FuncAnimation(fig, animate, interval = 100, blit = False)

输出:

data = np.stack([GA_X, GA_Y], axis = 2)

axis = normalize_axis_index(axis, result_ndim)

AxisError: axis 2 is out of bounds for array of dimension 2

Tags: importdatatimeasnp时间动画ax
1条回答
网友
1楼 · 发布于 2024-06-25 05:58:40

根据我的理解,您希望在每个时间步i为每个项目绘制一条线,其中每条线的两点首先是时间步i中的(x,y),其次是时间步i+1中的点(x,y)

(因此,如果项目没有出现在时间步长i+1中,我们将不会在步骤i中显示该项目的行)

假设如此,我建议:

1)使用数据帧本身,而不是将其更改为np.array

2)在动画功能中移动线的创建

import matplotlib.pyplot as plt
from matplotlib import animation
from numpy import random 
import random
import pandas as pd
import numpy as np


df1 = pd.DataFrame({
    'Time' : [1,1,1,1,2,2,2,2,3,3,3,4,4,4],  
    'Item' : ['A', 'B', 'C', 'D','A', 'B', 'C', 'D', 'A', 'B', 'C', 'A', 'B', 'C'],                  
    'GroupA_X' : [3, 4, 5, 1, 2, 5, 6, 2, 1, 6, 7, 2, 7, 8], 
    'GroupA_Y' : [2, 4, 5, 1, 2, 5, 5, 2, 2, 6, 5, 1, 5, 4],                         
        })

# generating the figure configs
frame_num = len(df1['Time'].unique()) 
fig = plt.figure()
ax1 = plt.axes(xlim=(0, 10), ylim=(0, 10))
line, = ax1.plot([], [], lw=2)
plt.xlabel('X')
plt.ylabel('Y')

plotlays, itemColors = [2], {'A':"black",
                             'B':"red",
                             'C':"blue",
                             'D':"purple"}


def animate(i):

    lines = []
    # filtering items per time step
    for (row_idx, row) in df1[df1["Time"] == i+1].iterrows():
        nextTimestep_item = df1[(df1["Time"] == i+2) & (df1["Item"] ==row["Item"])] 
        if nextTimestep_item.empty:
            # no plot if item is not on next timestep
            continue
        else:
            x = [row['GroupA_X'],nextTimestep_item['GroupA_X']]
            y = [row['GroupA_Y'],nextTimestep_item['GroupA_Y']]
            color = itemColors[row["Item"]]
            lobj = ax1.plot([],[],lw=2,color=color)[0]
            lobj.set_data(x, y)  
            lines.append(lobj)

    return lines

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, 
                               frames=frame_num, interval=500, blit=True)

plt.show()

相关问题 更多 >