I need to draw multiple matploblib chart using a for loop.
I have a data from with multiple column of data points and a time series 'year'. I need to create chart for each column.
I have the following code:
df=pd.DataFrame({'Time':['2014','2015','2016','2017','2018','2019'],
'A':[1,8,3,10,5,6],
'B':[2,3,5,2,3,5],
'C':[7,4,12,11,8,1],
'D':[3,4,2,2,7,7]})
x_pos=range(len(df['Time']))
m,c = np.polyfit(x_pos,df['A'],1)
plt.scatter(x=x_pos,y='A',data=df)
plt.plot(x_pos,m*x_pos+c,'--r')
any help is appreciated
I was able to figure it out. I used the matplotlib.gridspec to achieve this.
Following is the solution:
df=pd.DataFrame({'Time':['2014','2015','2016','2017','2018','2019'],
'A':[1,8,3,10,5,6],
'B':[2,3,5,2,3,5],
'C':[7,4,12,11,8,1],
'D':[3,4,2,2,7,7]})
#import gridspec to fit subplots
import matplotlib.gridspec as gridspec
fig = plt.figure(figsize=(10,10))
# set grid size 2*2
ggpec = gridspec.GridSpec(2, 2)
getaxs = []
datacolumns = list(df[['A','B','C','D']])
for i,j in zip(datacolumns,range(1,len(datacolumns)+1)):
xpos=range(len(df['Time']))
getaxs.append(fig.add_subplot(ggpec[j - 1]))
m,c = np.polyfit(x_pos,df['A'],1)
getaxs[-1].scatter(x=xpos,y=i,data=df)
getaxs[-1].plot(x_pos,m*x_pos+c,'--r')
plt.show()
The final result will be something like following:
Related
I have a scatterplot figure with subplots generated using a for loop. Within the figure, I am trying to create a single legend but each time a subplot and legend is rendered the legend is overwritten by the next subplot, so the figure that is generated contains a single legend pertaining only to the last subplot. I would like the legend to pertain to all subplots (i.e., it should include years 2019, 2020, 2021 and 2022). Here is my code, please let me know how I can tweak it.
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches
df = pd.read_excel(path)
spp = df.SPP.unique()
fig, axs = plt.subplots(nrows=8, ncols=4, figsize=(14, 14))
for spp_i, ax in zip(spp, axs.flat):
df_1 = df[df['SPP'] == spp_i]
labels = list(df_1.Year.unique())
x = df_1['Length_mm']
y = df_1['Weight_g']
levels, categories = pd.factorize(df_1['Year'])
colors = [plt.cm.tab10(i) for i in levels]
handles = [matplotlib.patches.Patch(color=plt.cm.tab10(i), label=c) for i, c in enumerate(categories)]
ax.scatter(x, y, c=colors)
plt.legend(handles=handles)
plt.savefig('Test.png', bbox_inches='tight', pad_inches=0.1, dpi=600)
Here is figure, as you can see the legend in the bottom right is for the last subplot only.
enter image description here
Creating this type of plots is quite cumbersome with standard matplotlib. Seaborn automates a lot of the steps.
In this case, sns.relplot(...) can be used. If you don't want all the subplots to have the same x and/or y ranges, you can add facet_kws={'sharex': False, 'sharey': False}).
The size of the individual subplots is controlled via height=, while the width will be calculated as the height multiplied by the aspect. col_wrap= tells how many columns of subplots will be put before starting a new row.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
spp_list = ["Aeloria", "Baelun", "Caelondia", "Draeden", "Eldrida", "Faerun", "Gorandor", "Haldira", "Ilysium",
"Jordheim", "Kaltara", "Lorlandia", "Myridia", "Nirathia", "Oakenfort"]
df = pd.DataFrame({'SPP': np.repeat(spp_list, 100),
'Year': np.tile(np.repeat(np.arange(2019, 2023), 25), 15),
'Length_mm': np.abs(np.random.randn(1500).cumsum()) + 10,
'Weight_g': np.abs(np.random.randn(1500).cumsum()) + 20})
g = sns.relplot(df, x='Length_mm', y='Weight_g', col='SPP', col_order=spp_list,
hue='Year', palette='turbo',
height=3, aspect=1.5, col_wrap=6,
facet_kws={'sharex': False, 'sharey': False})
g.set_axis_labels(x_var='Length (mm)', y_var='Weight (g)', clear_inner=True)
g.fig.tight_layout() # nicely fit supblots with their titles, labels and ticks
g.fig.subplots_adjust(right=0.97) # space for the legend after fitting the subplots
plt.show()
Please tell me so as to what should i do to solve this problem or what values should i put to solve this problem
while(True):
ret,img = source.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces=face_clsfr.detectMultiScale(gray,1.3,5)
for x,y,w,h in faces:
face_img = gray[y:y+w,x:x+w]
resized = cv2.resize(face_img,(100,100))
normalized=resized/255,0
reshaped = np.reshape(normalized, (1,100,100,1))
result=model.predict(reshaped)
label=np.argmax(result,axis=1)[0]
cv2.rectangle(img,(x,y),(x+w,y+h), colordict[label],2)
cv2.rectangle(img,(x,y-40),(x+w,y), colordict[label],-1)
cv2.putText(img,labels_dict[label], (x,y-10), cv2.FONT_HERSHEY_SIMPLEX,0.8,(255,255,255),2)
cv2.imshow('Frame',img)
key=cv2.waitKey(1)
if(key=='q'):
break
cv2.destroyAllWindows()
source.release
You change the array type of image to a tuple in:
normalized = resized/255,0
change to:
normalized = resized/255
I face this issue and can't seem to find a fix except with Scipy or Numpy, both of which I don't wanna use in this case.
From a .csv file, I want to extract the values of the first column :
enter image description here
Which I manage to do with the following code :
mat_data = open('file.csv')
data_reader = csv.reader(mat_data)
list_data = list(data_reader)
value1=float(list_data[1][0])
value2=float(list_data[2][0])
value3=float(list_data[3][0])
I'd now like to create a loop that could be used and create value"i" no matter how many lines long my .csv is.
Any idea?
This did the trick for me !
mat_data = open('file.csv')
data_reader = csv.reader(mat_data)
list_data = list(data_reader)
i=0
value=dict()
for i in range(1,len(list_data)):
value[i]=list_data[i][0]
print value[i]
I'm trying to create a script that will automatically format a selection based on the formatting of a table in another sheet. The idea is that a user can define a table style for header, rowOdd and rowEven in the Formats sheet, then easily apply it to a selected table using the script.
I've managed to get it working, but only by applying one type of formatting (background colour).
I based my code for reading the code into an array on this article.
As you will hopefully see from my code below, I am only able to read one formatting property into my array.
What I would like to do is read all formatting properties into the array, then apply them to the range in one go. I'm new to this so sorry if my code is a mess!
function formatTable() {
var activeRange = SpreadsheetApp.getActiveSpreadsheet().getActiveRange(); //range to apply formatting to
var arr = new Array(activeRange.getNumRows());
var tableStyleSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Formats"); //location of source styles
var tableColours = {
header: tableStyleSheet.getRange(1, 1, 1).getBackground(),
rowEven: tableStyleSheet.getRange(2, 1, 1).getBackground(),
rowOdd: tableStyleSheet.getRange(3, 1, 1).getBackground()
}
for (var x = 0; x < activeRange.getNumRows(); x++) {
arr[x] = new Array(activeRange.getNumColumns());
for (var y = 0; y < activeRange.getNumColumns(); y++) {
x == 0 ? arr[x][y] = tableColours.header :
x % 2 < 1 ? arr[x][y] = tableColours.rowOdd : arr[x][y] = tableColours.rowEven;
Logger.log(arr);
}
}
activeRange.setBackgrounds(arr);
}
Thanks!
I might be wrong but based from the list of methods given in Class Range, feature to save or store formatting details currently do not exist yet.
However, you may want to try using the following:
copyFormatToRange(gridId, column, columnEnd, row, rowEnd) or copyFormatToRange(sheet, column, columnEnd, row, rowEnd) wherein it copies the formatting of the range to the given location.
moveTo(target) wherein it cuts and paste (both format and values) from this range to the target range.
Did you know that you can get all of the different formatting elements for a range straight into an array?
E.g.
var backgrounds = sheet.getRange("A1:D50").getBackgrounds();
var fonts = sheet.getRange("A1:D50").getFontFamilies();
var fontcolors = sheet.getRange("A1:D50").getFontColors();
etc.
However, there's no way to get all of the formatting in one call unfortunately, so you have to handle each element separately. Then you can apply all of the formats in one go:
targetRng.setFontColors(fontcolors);
targetRng.setBackgrounds(backgrounds);
and so on.
Okay. i have this problem in line graph. Tickmarks(data-points) are not aligned with vertical grid lines. is there a way to achieve that.please help?
you number of tick marks need to match the number of vlines. What I often do is I will get the count of my labels variable (with javascript) and so something like this.
var numTicks = labelVariable.length;
Then on draw of the graph
options: {
numxticks: num_ticks
}
var xticks = 10;
or with php
var xticks = "<php echo $yourvariable ;?>";
var line = .......
.set('chart.numxticks',xticks)