Reputation: 686
Here is a dataframe showing coordinates of 5 different points. How can it be animated row by row?
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
Column x1,y1 is the coordinates of the first ant. Sequentially x2,y2 x3,y3 .. represents the coordinates of other ants. Indexes show the steps where in every step ants go from one node to another node. I used plotly to animate the data
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])
But it only shows the 1st point(x1,y1), How can I animate all 5 points in single plot?
Here is the data of first 100 rows:
{'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}}
Upvotes: 1
Views: 456
Reputation: 61094
If the first frame of what you're aiming to build looks like this:
And the last frame should look like this:
Then you should reshape your dataframe from a wide to a long format for each category x
and y
so that animation_frame
has something else than a continuous index to work with. And then assign extracted numbers from x1, y1
to the animation_group
attribute in px.scatter
:
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])
Upvotes: 1
Reputation: 2252
Tried to edit @vestland's answer, but canceled and now the queue is full... My bad. Seems to be a little inelegant way to reshape, but here's how I did it. You can only see four points in the image because two are in the same location.
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])
Upvotes: 2