如何在单个散点图中为多个移动点设置动画
Posted
技术标签:
【中文标题】如何在单个散点图中为多个移动点设置动画【英文标题】:How to animate multiple moving points in single scatter plot 【发布时间】:2021-07-04 11:16:14 【问题描述】:这是一个显示 5 个不同点坐标的数据框。怎么能逐行动画呢?
x1 y1 x2 y2 x3 y3 x4 y4 x5 y5
0 12 22 12 22 12 22 12 22 12 22
1 6 29 17 10 24 19 17 10 6 29
2 24 19 24 19 21 26 24 19 21 26
3 21 26 6 29 17 10 6 29 24 19
4 17 10 21 26 6 29 21 26 17 10
... ... ... ... ... ... ... ... ... ... ...
11995 17 10 17 10 17 10 17 10 17 10
11996 24 19 24 19 24 19 24 19 24 19
11997 21 26 21 26 21 26 21 26 21 26
11998 6 29 6 29 6 29 6 29 6 29
11999 12 22 12 22 12 22 12 22 12 22
x1,y1 列是第一只蚂蚁的坐标。依次为 x2,y2 x3,y3 .. 表示其他蚂蚁的坐标。索引显示蚂蚁在每一步中从一个节点到另一个节点的步骤。 我用 plotly 动画数据
import plotly.express as px
px.scatter(dftempt, x=dftempt.x1, y=dftempt.y1, animation_frame=dftempt.index, range_x=[0,30], range_y=[0,30])
但它只显示第一个点(x1,y1),我怎样才能在单个图中为所有 5 个点设置动画?
这是前100行的数据:
'x1': 0: 5, 1: 29, 2: 14, 3: 21, 4: 26, 5: 5, 6: 5, 7: 29, 8: 14, 9: 21, 10: 26, 11: 5, 12: 5, 13: 29, 14: 14, 15: 21, 16: 26, 17: 5, 18: 5, 19: 29, 20: 14, 21: 21, 22: 26, 23: 5, 24: 5, 25: 29, 26: 14, 27: 21, 28: 26, 29: 5, 30: 5, 31: 29, 32: 14, 33: 21, 34: 26, 35: 5, 36: 5, 37: 29, 38: 14, 39: 21, 40: 26, 41: 5, 42: 5, 43: 29, 44: 14, 45: 21, 46: 26, 47: 5, 48: 5, 49: 29, 50: 14, 51: 21, 52: 26, 53: 5, 54: 5, 55: 29, 56: 14, 57: 21, 58: 26, 59: 5, 60: 5, 61: 29, 62: 14, 63: 21, 64: 26, 65: 5, 66: 5, 67: 29, 68: 14, 69: 21, 70: 26, 71: 5, 72: 5, 73: 29, 74: 14, 75: 21, 76: 26, 77: 5, 78: 5, 79: 29, 80: 14, 81: 21, 82: 26, 83: 5, 84: 5, 85: 29, 86: 14, 87: 21, 88: 26, 89: 5, 90: 5, 91: 29, 92: 14, 93: 21, 94: 26, 95: 5, 96: 5, 97: 29, 98: 14, 99: 21, 'y1': 0: 20, 1: 9, 2: 29, 3: 23, 4: 24, 5: 20, 6: 20, 7: 9, 8: 29, 9: 23, 10: 24, 11: 20, 12: 20, 13: 9, 14: 29, 15: 23, 16: 24, 17: 20, 18: 20, 19: 9, 20: 29, 21: 23, 22: 24, 23: 20, 24: 20, 25: 9, 26: 29, 27: 23, 28: 24, 29: 20, 30: 20, 31: 9, 32: 29, 33: 23, 34: 24, 35: 20, 36: 20, 37: 9, 38: 29, 39: 23, 40: 24, 41: 20, 42: 20, 43: 9, 44: 29, 45: 23, 46: 24, 47: 20, 48: 20, 49: 9, 50: 29, 51: 23, 52: 24, 53: 20, 54: 20, 55: 9, 56: 29, 57: 23, 58: 24, 59: 20, 60: 20, 61: 9, 62: 29, 63: 23, 64: 24, 65: 20, 66: 20, 67: 9, 68: 29, 69: 23, 70: 24, 71: 20, 72: 20, 73: 9, 74: 29, 75: 23, 76: 24, 77: 20, 78: 20, 79: 9, 80: 29, 81: 23, 82: 24, 83: 20, 84: 20, 85: 9, 86: 29, 87: 23, 88: 24, 89: 20, 90: 20, 91: 9, 92: 29, 93: 23, 94: 24, 95: 20, 96: 20, 97: 9, 98: 29, 99: 23, 'x2': 0: 5, 1: 26, 2: 14, 3: 21, 4: 29, 5: 5, 6: 5, 7: 26, 8: 14, 9: 21, 10: 29, 11: 5, 12: 5, 13: 26, 14: 14, 15: 21, 16: 29, 17: 5, 18: 5, 19: 26, 20: 14, 21: 21, 22: 29, 23: 5, 24: 5, 25: 26, 26: 14, 27: 21, 28: 29, 29: 5, 30: 5, 31: 26, 32: 14, 33: 21, 34: 29, 35: 5, 36: 5, 37: 26, 38: 14, 39: 21, 40: 29, 41: 5, 42: 5, 43: 26, 44: 14, 45: 21, 46: 29, 47: 5, 48: 5, 49: 26, 50: 14, 51: 21, 52: 29, 53: 5, 54: 5, 55: 26, 56: 14, 57: 21, 58: 29, 59: 5, 60: 5, 61: 26, 62: 14, 63: 21, 64: 29, 65: 5, 66: 5, 67: 26, 68: 14, 69: 21, 70: 29, 71: 5, 72: 5, 73: 26, 74: 14, 75: 21, 76: 29, 77: 5, 78: 5, 79: 26, 80: 14, 81: 21, 82: 29, 83: 5, 84: 5, 85: 26, 86: 14, 87: 21, 88: 29, 89: 5, 90: 5, 91: 26, 92: 14, 93: 21, 94: 29, 95: 5, 96: 5, 97: 26, 98: 14, 99: 21, 'y2': 0: 20, 1: 24, 2: 29, 3: 23, 4: 9, 5: 20, 6: 20, 7: 24, 8: 29, 9: 23, 10: 9, 11: 20, 12: 20, 13: 24, 14: 29, 15: 23, 16: 9, 17: 20, 18: 20, 19: 24, 20: 29, 21: 23, 22: 9, 23: 20, 24: 20, 25: 24, 26: 29, 27: 23, 28: 9, 29: 20, 30: 20, 31: 24, 32: 29, 33: 23, 34: 9, 35: 20, 36: 20, 37: 24, 38: 29, 39: 23, 40: 9, 41: 20, 42: 20, 43: 24, 44: 29, 45: 23, 46: 9, 47: 20, 48: 20, 49: 24, 50: 29, 51: 23, 52: 9, 53: 20, 54: 20, 55: 24, 56: 29, 57: 23, 58: 9, 59: 20, 60: 20, 61: 24, 62: 29, 63: 23, 64: 9, 65: 20, 66: 20, 67: 24, 68: 29, 69: 23, 70: 9, 71: 20, 72: 20, 73: 24, 74: 29, 75: 23, 76: 9, 77: 20, 78: 20, 79: 24, 80: 29, 81: 23, 82: 9, 83: 20, 84: 20, 85: 24, 86: 29, 87: 23, 88: 9, 89: 20, 90: 20, 91: 24, 92: 29, 93: 23, 94: 9, 95: 20, 96: 20, 97: 24, 98: 29, 99: 23, 'x3': 0: 5, 1: 26, 2: 14, 3: 21, 4: 29, 5: 5, 6: 5, 7: 26, 8: 14, 9: 21, 10: 29, 11: 5, 12: 5, 13: 26, 14: 14, 15: 21, 16: 29, 17: 5, 18: 5, 19: 26, 20: 14, 21: 21, 22: 29, 23: 5, 24: 5, 25: 26, 26: 14, 27: 21, 28: 29, 29: 5, 30: 5, 31: 26, 32: 14, 33: 21, 34: 29, 35: 5, 36: 5, 37: 26, 38: 14, 39: 21, 40: 29, 41: 5, 42: 5, 43: 26, 44: 14, 45: 21, 46: 29, 47: 5, 48: 5, 49: 26, 50: 14, 51: 21, 52: 29, 53: 5, 54: 5, 55: 26, 56: 14, 57: 21, 58: 29, 59: 5, 60: 5, 61: 26, 62: 14, 63: 21, 64: 29, 65: 5, 66: 5, 67: 26, 68: 14, 69: 21, 70: 29, 71: 5, 72: 5, 73: 26, 74: 14, 75: 21, 76: 29, 77: 5, 78: 5, 79: 26, 80: 14, 81: 21, 82: 29, 83: 5, 84: 5, 85: 26, 86: 14, 87: 21, 88: 29, 89: 5, 90: 5, 91: 26, 92: 14, 93: 21, 94: 29, 95: 5, 96: 5, 97: 26, 98: 14, 99: 21, 'y3': 0: 20, 1: 24, 2: 29, 3: 23, 4: 9, 5: 20, 6: 20, 7: 24, 8: 29, 9: 23, 10: 9, 11: 20, 12: 20, 13: 24, 14: 29, 15: 23, 16: 9, 17: 20, 18: 20, 19: 24, 20: 29, 21: 23, 22: 9, 23: 20, 24: 20, 25: 24, 26: 29, 27: 23, 28: 9, 29: 20, 30: 20, 31: 24, 32: 29, 33: 23, 34: 9, 35: 20, 36: 20, 37: 24, 38: 29, 39: 23, 40: 9, 41: 20, 42: 20, 43: 24, 44: 29, 45: 23, 46: 9, 47: 20, 48: 20, 49: 24, 50: 29, 51: 23, 52: 9, 53: 20, 54: 20, 55: 24, 56: 29, 57: 23, 58: 9, 59: 20, 60: 20, 61: 24, 62: 29, 63: 23, 64: 9, 65: 20, 66: 20, 67: 24, 68: 29, 69: 23, 70: 9, 71: 20, 72: 20, 73: 24, 74: 29, 75: 23, 76: 9, 77: 20, 78: 20, 79: 24, 80: 29, 81: 23, 82: 9, 83: 20, 84: 20, 85: 24, 86: 29, 87: 23, 88: 9, 89: 20, 90: 20, 91: 24, 92: 29, 93: 23, 94: 9, 95: 20, 96: 20, 97: 24, 98: 29, 99: 23, 'x4': 0: 5, 1: 26, 2: 14, 3: 21, 4: 29, 5: 5, 6: 5, 7: 26, 8: 14, 9: 21, 10: 29, 11: 5, 12: 5, 13: 26, 14: 14, 15: 21, 16: 29, 17: 5, 18: 5, 19: 26, 20: 14, 21: 21, 22: 29, 23: 5, 24: 5, 25: 26, 26: 14, 27: 21, 28: 29, 29: 5, 30: 5, 31: 26, 32: 14, 33: 21, 34: 29, 35: 5, 36: 5, 37: 26, 38: 14, 39: 21, 40: 29, 41: 5, 42: 5, 43: 26, 44: 14, 45: 21, 46: 29, 47: 5, 48: 5, 49: 26, 50: 14, 51: 21, 52: 29, 53: 5, 54: 5, 55: 26, 56: 14, 57: 21, 58: 29, 59: 5, 60: 5, 61: 26, 62: 14, 63: 21, 64: 29, 65: 5, 66: 5, 67: 26, 68: 14, 69: 21, 70: 29, 71: 5, 72: 5, 73: 26, 74: 14, 75: 21, 76: 29, 77: 5, 78: 5, 79: 26, 80: 14, 81: 21, 82: 29, 83: 5, 84: 5, 85: 26, 86: 14, 87: 21, 88: 29, 89: 5, 90: 5, 91: 26, 92: 14, 93: 21, 94: 29, 95: 5, 96: 5, 97: 26, 98: 14, 99: 21, 'y4': 0: 20, 1: 24, 2: 29, 3: 23, 4: 9, 5: 20, 6: 20, 7: 24, 8: 29, 9: 23, 10: 9, 11: 20, 12: 20, 13: 24, 14: 29, 15: 23, 16: 9, 17: 20, 18: 20, 19: 24, 20: 29, 21: 23, 22: 9, 23: 20, 24: 20, 25: 24, 26: 29, 27: 23, 28: 9, 29: 20, 30: 20, 31: 24, 32: 29, 33: 23, 34: 9, 35: 20, 36: 20, 37: 24, 38: 29, 39: 23, 40: 9, 41: 20, 42: 20, 43: 24, 44: 29, 45: 23, 46: 9, 47: 20, 48: 20, 49: 24, 50: 29, 51: 23, 52: 9, 53: 20, 54: 20, 55: 24, 56: 29, 57: 23, 58: 9, 59: 20, 60: 20, 61: 24, 62: 29, 63: 23, 64: 9, 65: 20, 66: 20, 67: 24, 68: 29, 69: 23, 70: 9, 71: 20, 72: 20, 73: 24, 74: 29, 75: 23, 76: 9, 77: 20, 78: 20, 79: 24, 80: 29, 81: 23, 82: 9, 83: 20, 84: 20, 85: 24, 86: 29, 87: 23, 88: 9, 89: 20, 90: 20, 91: 24, 92: 29, 93: 23, 94: 9, 95: 20, 96: 20, 97: 24, 98: 29, 99: 23, 'x5': 0: 5, 1: 14, 2: 21, 3: 26, 4: 29, 5: 5, 6: 5, 7: 14, 8: 21, 9: 26, 10: 29, 11: 5, 12: 5, 13: 14, 14: 21, 15: 26, 16: 29, 17: 5, 18: 5, 19: 14, 20: 21, 21: 26, 22: 29, 23: 5, 24: 5, 25: 14, 26: 21, 27: 26, 28: 29, 29: 5, 30: 5, 31: 14, 32: 21, 33: 26, 34: 29, 35: 5, 36: 5, 37: 14, 38: 21, 39: 26, 40: 29, 41: 5, 42: 5, 43: 14, 44: 21, 45: 26, 46: 29, 47: 5, 48: 5, 49: 14, 50: 21, 51: 26, 52: 29, 53: 5, 54: 5, 55: 14, 56: 21, 57: 26, 58: 29, 59: 5, 60: 5, 61: 14, 62: 21, 63: 26, 64: 29, 65: 5, 66: 5, 67: 14, 68: 21, 69: 26, 70: 29, 71: 5, 72: 5, 73: 14, 74: 21, 75: 26, 76: 29, 77: 5, 78: 5, 79: 14, 80: 21, 81: 26, 82: 29, 83: 5, 84: 5, 85: 14, 86: 21, 87: 26, 88: 29, 89: 5, 90: 5, 91: 14, 92: 21, 93: 26, 94: 29, 95: 5, 96: 5, 97: 14, 98: 21, 99: 26, 'y5': 0: 20, 1: 29, 2: 23, 3: 24, 4: 9, 5: 20, 6: 20, 7: 29, 8: 23, 9: 24, 10: 9, 11: 20, 12: 20, 13: 29, 14: 23, 15: 24, 16: 9, 17: 20, 18: 20, 19: 29, 20: 23, 21: 24, 22: 9, 23: 20, 24: 20, 25: 29, 26: 23, 27: 24, 28: 9, 29: 20, 30: 20, 31: 29, 32: 23, 33: 24, 34: 9, 35: 20, 36: 20, 37: 29, 38: 23, 39: 24, 40: 9, 41: 20, 42: 20, 43: 29, 44: 23, 45: 24, 46: 9, 47: 20, 48: 20, 49: 29, 50: 23, 51: 24, 52: 9, 53: 20, 54: 20, 55: 29, 56: 23, 57: 24, 58: 9, 59: 20, 60: 20, 61: 29, 62: 23, 63: 24, 64: 9, 65: 20, 66: 20, 67: 29, 68: 23, 69: 24, 70: 9, 71: 20, 72: 20, 73: 29, 74: 23, 75: 24, 76: 9, 77: 20, 78: 20, 79: 29, 80: 23, 81: 24, 82: 9, 83: 20, 84: 20, 85: 29, 86: 23, 87: 24, 88: 9, 89: 20, 90: 20, 91: 29, 92: 23, 93: 24, 94: 9, 95: 20, 96: 20, 97: 29, 98: 23, 99: 24
【问题讨论】:
【参考方案1】:试图编辑@vestland 的答案,但取消了,现在队列已满……我的错。似乎是一种有点不雅的重塑方式,但这就是我的做法。您只能在图像中看到四个点,因为两个点位于同一位置。
import plotly_express as px
import pandas as pd
df = pd.DataFrame('x1': 0: 12, 1: 6, 2: 24, 3: 21, 4: 17,
'y1': 0: 22, 1: 29, 2: 19, 3: 26, 4: 10,
'x2': 0: 12, 1: 17, 2: 24, 3: 6, 4: 21,
'y2': 0: 22, 1: 10, 2: 19, 3: 29, 4: 26,
'x3': 0: 12, 1: 24, 2: 21, 3: 17, 4: 6,
'y3': 0: 22, 1: 19, 2: 26, 3: 10, 4: 29,
'x4': 0: 12, 1: 17, 2: 24, 3: 6, 4: 21,
'y4': 0: 22, 1: 10, 2: 19, 3: 29, 4: 26,
'x5': 0: 12, 1: 6, 2: 21, 3: 24, 4: 17,
'y5': 0: 22, 1: 29, 2: 26, 3: 19, 4: 10)
dftempt = df
point_lst = []
for i in range(len(dftempt.columns) // 2):
point = 'point' + str(i+1)
dftempt[point] = df[df.columns[2*i:2*i+2]].apply(lambda x: list(x) + [point], axis=1)
point_lst.append(point)
dftempt = pd.concat(dftempt[point] for point in point_lst).reset_index().rename(columns=0:'data')
dftempt[['x','y','points']] = pd.DataFrame(dftempt.data.tolist(), index= dftempt.index)
px.scatter(dftempt, x='x', y='y', animation_frame='index', animation_group='points', range_x=[0,30], range_y=[0,30])
【讨论】:
非常感谢,这是我正在寻找的答案。不知道animation_group。【参考方案2】:如果您要构建的第一帧如下所示:
最后一帧应该是这样的:
然后,您应该将每个类别 x
和 y
的数据框从宽格式重新调整为长格式,这样 animation_frame
就可以使用除连续索引之外的其他内容。然后将从x1, y1
中提取的数字分配给px.scatter
中的animation_group
属性:
px.scatter(dftempt, x='x', y='y', animation_frame='index', animation_group='variable', range_x=[0,30], range_y=[0,30])
完整代码:
import pandas as pd
import plotly.express as px
df = pd.DataFrame('x1': 0: 12, 1: 6, 2: 24, 3: 21, 4: 17,
'y1': 0: 22, 1: 29, 2: 19, 3: 26, 4: 10,
'x2': 0: 12, 1: 17, 2: 24, 3: 6, 4: 21,
'y2': 0: 22, 1: 10, 2: 19, 3: 29, 4: 26,
'x3': 0: 12, 1: 24, 2: 21, 3: 17, 4: 6,
'y3': 0: 22, 1: 19, 2: 26, 3: 10, 4: 29,
'x4': 0: 12, 1: 17, 2: 24, 3: 6, 4: 21,
'y4': 0: 22, 1: 10, 2: 19, 3: 29, 4: 26,
'x5': 0: 12, 1: 6, 2: 21, 3: 24, 4: 17,
'y5': 0: 22, 1: 29, 2: 26, 3: 19, 4: 10)
# isolate and reshape x
xx = [c for c in df.columns if 'x' in c]
dfx = df[xx]
dfxm =pd.melt(dfx.reset_index(), id_vars=['index'], value_vars=dfx.columns)
dfxm['variable'] = dfxm['variable'].str.extract('(\d+)')
dfxm.rename(columns="value": "x", inplace=True)
# dfxm
# isolate and reshape y
yy = [c for c in df.columns if 'y' in c]
dfy = df[yy]
dfym =pd.melt(dfy.reset_index(), id_vars=['index'], value_vars=dfy.columns)
dfym['variable'] = dfym['variable'].str.extract('(\d+)')
dfym.rename(columns="value": "y", inplace=True)
dfym['x'] = dfxm['x']
dftempt = dfym
px.scatter(dftempt, x='x', y='y', animation_frame='index', animation_group='variable', range_x=[0,30], range_y=[0,30])
【讨论】:
这是蚁群优化的步骤。我正在寻找根据 (x1,y1) (x2,y2)... 放置蚂蚁...其中 x 和 y 轴将保持从 0 到 30 的值。并且在每个索引中,动画函数将显示它们的当前节点 哇,太好了!变量 animation_group 让我们在每个轴上使用融化的变量。这个概念将有助于更高的维度。以上是关于如何在单个散点图中为多个移动点设置动画的主要内容,如果未能解决你的问题,请参考以下文章