1
votes

I have an Excel sheet that has a column of image frames. These frames numbers are not uniformly distributed, e.g. frame 1 may have entries from row 1 to 20 and frame 2 from 21 to 25 and so on. I want to read this data from an Excel sheet that has x and y coordinate for each frame and plot these x and y coordinate in a scattered plot using matplotlib. Here's my code, frame numbers are identified as image index.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from matplotlib.pyplot import figure

df_xlsx = pd.read_excel('X10.xlsx')
temp = df_xlsx['Image index'][0]
i = 0; #number of the row

xList = []
yList = []
dt = df_xlsx.loc[df_xlsx['Image index'] == 19]
xList = np.array(dt['X position'])
yList = np.array(dt['Y position'])
rList = np.array(dt['Diameter'])

figure(figsize=(10.24,7.68), dpi=100)
fig, ax = plt.subplots()
plt.xlim([0,1024])
plt.ylim([0,768])
plt.scatter(xList, yList, color ='r')
plt.axis('off')
plt.gcf().set_size_inches((10.24,7.68))

for i in range(len(xList)):
    circle1 = plt.Circle((xList[i], yList[i]), rList[i], color='r')
    ax.add_artist(circle1)
plt.tight_layout(pad=0)
plt.savefig('f=19.png',dpi=100)    
plt.show()

Excel sheet example

The problem is every time I need to enter the image index and then save the plot. Can this be done in a loop such that the plot is continuously generated as different plots for each frame number (index frames)? This will save me a lot of time, as I have lots of frames and excel sheets. I am new to Python.

1
Welcome to SO. some remarks for your code: df_xlsx = pd.read_excel('X10.xlsx') won't work unless you are working with a very old version of pandas. Better update your pandas to a newer version. By excel sheet do you mean file or an actual sheet (sheet1, sheet2, ...)? - Karina

1 Answers

0
votes

You can use groupby to step over the image index:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_excel('X10.xlsx')

for idx, group in df.groupby('Image index'):
    fig, ax = plt.subplots(figsize=(10.24, 7.68), dpi=100)
    diameter = 1 * group['Diameter']**2
    ax.scatter(group['X position'], group['Y position'], s=diameter)
    ax.set_xlim(0, 1024)
    ax.set_ylim(0, 768)
    ax.axis('off')
    plt.tight_layout(pad=0)
    plt.savefig(f'Image_index_{idx}.png', dpi=100)    

Some notes on the other changes I made:

  • You don't need to cast the DataFrame columns to arrays or lists.
  • You can pass a size parameter s to plt.scatter() to make the circles; you'll just need to scale the numbers to fit your scale. E.g. you could multiply by some factor other than 1. Note that in matplotlib you are specifying the area of the marker, not the diameter.