How to increase size of plot using 'ax' and ensure that 'y'-axis ticks are actual values instead of 'le11' - python-3.x

I am trying to plot a bar graph using a dataframe, and I used the below code:
def add_line(ax, xpos, ypos):
line = plt.Line2D([xpos, xpos], [ypos + .1, ypos],
transform=ax.transAxes, color='gray')
line.set_clip_on(False)
ax.add_line(line)
def label_len(my_index,level):
labels = my_index.get_level_values(level)
return [(k, sum(1 for i in g)) for k,g in groupby(labels)]
def label_group_bar_table(ax, df):
ypos = -.1
scale = 1./df.index.size
for level in range(df.index.nlevels)[::-1]:
pos = 0
for label, rpos in label_len(df.index,level):
lxpos = (pos + .5 * rpos)*scale
ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes)
add_line(ax, pos*scale, ypos)
pos += rpos
add_line(ax, pos*scale , ypos)
ypos -= .1
from matplotlib.pyplot import figure
ax = my_df.plot(kind='bar')
ax.set_xticklabels('State')
ax.set_xlabel('Electricity consumed by every resource')
ax.plot([1,2,3])
#plt.xticks(rotation=90)
label_group_bar_table(ax, my_df)
My question is: How do I change the size of the plot and how can I make sure that the ticks are displayed vertically on the x-axis and ensure that the title of the x-axis and the ticks on the x-axis don't overlap?
While using 'figure', I know that the 'rotation' parameter can be changed to 90 to ensure that x ticks are vertical. I also understand that the 'figsize' can be used to set the size while using figure. But I am not sure how we should work with 'ax'.
Why are my y-axis ticks in decimal and what is that 'le11'? My data contains numbers that are 7 digit or 8 digits. Is there a way to ensure the y-axis also contains 7 or 8 digit numbers instead?
My graph looks like:

Related

discrete colorbar with discrete colormesh

I want to realize a colour plot of a matrix. The rules for this kind of plot are:
if -5 < my_matrix[i,j] < 8 use white.
if 8 < my_matrix[i,j] < 20 use black.
if 20 < my_matrix[i,j] < 30 use red.
if my_matrix[i,j] > 30 use green.
Here is the code, as you can see the matrix is random. I have also printed a text plot in order to check if the print is correct.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
Z_1 = 8
Z_2 = 20
Z_3 = 30
period = 5
size = 10
np.random.seed(1)
my_matrix = np.random.randint(-4,50,[period,size])
my_matrix[0,0] = 33
my_matrix[1,0] = 31
print(" ")
print(my_matrix.T)
print(" ")
bounds = [-5,Z_1,Z_2,Z_3]
cmap = colors.ListedColormap(['white', 'black','red','green' ]).with_extremes(over='green')
pm=plt.pcolormesh(my_matrix.T, cmap = cmap)
plt.colorbar(pm, boundaries = bounds ,extend = 'max', extendfrac='auto' ,ticks=bounds)
for i in range(len(my_matrix[:,0])):
for j in range(len(my_matrix[0,:])):
plt.text(i,j,str(my_matrix[i,j]), va='center_baseline', ha='left',color = 'blue')
#plt.clim(0, 31)
plt.gca().invert_yaxis()
plt.show()
I think the command .with_extremes(over='...') is useful for this kind of plot.
Unfortunately I get the following picture. The green colour is not present and some bound are not respected (see my_matrix(0)(1) or my_matrix(1)(0)).
I want to have a plot with the aforementioned rules which has all the related colours in the colorbar, also taking into account those values greater than 30.
You can use a BoundaryNorm to set where the boundaries are. Also, you don't need to include green as a colour in the list of colours. For example:
bounds = [-5, Z_1, Z_2, Z_3]
cmap = colors.ListedColormap(['white', 'black', 'red']).with_extremes(over='green')
norm = colors.BoundaryNorm(bounds, cmap.N)
pm = plt.pcolormesh(my_matrix.T, cmap=cmap, norm=norm)
plt.colorbar(pm, extend='max', extendfrac='auto')

Python polar bar chart - Remove degrees & color one ring

I have been trying to create a polar bar chart in python for quite some time. After some research I managed to get the results that I wanted. Well, almost. There're still a couple thing that I don't know how to do.
I include my code:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import FixedLocator
from operator import add
#DATA MANIPULATION
dataset = pd.read_csv('Controls.csv', delimiter=";")
dataset.astype({'Rating':'float'})
#print(dataset.dtypes)
categories = dataset['Category'].drop_duplicates()
controls = dataset['Control'].drop_duplicates()
categ_avg = []
control_average = []
#Average for controls
for category in categories:
avg = 0
for index, item in dataset.iterrows():
if item['Category'] == category:
avg += item['Rating']
categ_avg.append(avg)
avg = 0
for control in controls:
avg = 0
for index, item in dataset.iterrows():
if item['Control'] == control:
avg += item['Rating']
control_average.append(avg)
avg = 0
average = [total / 5 for total in categ_avg]
avgdf = pd.DataFrame({
'Category' : categories,
#'Controls' : controls,
'Average' : average
})
#PLOTTING
#Compute pie slices which is the number of unique controls
N = len(controls)
#theta = np.linspace(0, 2 * np.pi, N, endpoint=False)
theta = [0]
for cat in categories:
if cat == 'CAT-A':
theta.append( theta[-1] + (2 * np.pi/N * 2) )
else:
theta.append( theta[-1] + (2*np.pi / N) )
print(theta)
#Compute the filling axis
mid_theta = []
for cat in categories:
if cat == 'CAT-A':
mid_theta.append( 2 * np.pi/N )
else:
mid_theta.append( 2 * np.pi / N / 2 )
mid_theta = list(map(add,theta, mid_theta))
print(mid_theta)
radii = avgdf['Average']
#width = theta[1] - theta[0]
width = []
for i in range(0, len(avgdf['Average'])):
width.append(theta[i+1] - theta[i])
fig = plt.figure()
fig.patch.set_facecolor('white')
fig.patch.set_alpha(0.5)
#Draw X labels
ax = fig.add_subplot(111, projection='polar')
ax.set_xticks(theta)
# Draw ylabels
ax.set_rlabel_position(0)
ax.set_yticks([1, 2, 3, 4, 5])
ax.set_yticklabels(["1", "2", "3", "4", "5"], color="black", size=8)
ax.set_ylim(0, 5)
#colors = plt.cm.hsv(theta/2/np.pi)
bars = ax.bar(mid_theta, radii, width=width, bottom=0.0)
#Labels
for bar, angle, label in zip(bars, mid_theta, avgdf["Category"]):
# Labels are rotated. Rotation must be specified in degrees :(
rotation = np.rad2deg(angle)
# Flip some labels upside down
alignment = ""
if angle >= np.pi/2 and angle < 3*np.pi/2:
alignment = "right"
rotation = rotation + 180
else:
alignment = "left"
# Finally add the labels
ax.text(
x=angle,
y=5.5,
s=label,
ha=alignment,
va='center')
#Use custom colors and opacity
for r, bar in zip(avgdf['Average'], bars):
bar.set_facecolor(plt.cm.viridis(r/5.))
bar.set_alpha(0.5)
plt.show()
When I execute it I obtain the following graph: Resulting graph
What I'm trying to achieve is:
I would like to color the ring number 4 in green.
I would like to remove the degrees from the outer ring. I only want to see my categories not the 0, 144ยบ...
I really appreciate the help.
Thanks you.
Create a list of colours with as many colours as you have polar bars.
c = ['blue', 'blue', 'blue', 'green', 'blue', 'blue']
bars = ax.bar(
x=angles,
height=heights,
width=width,
color=c,
linewidth=2,
edgecolor="white")

Changing Opacity by a function

I have created a 3d scatter plot that changes colour based around a separate variable, Intensity. Ideally I would change the opacity so that the lower intensity colours are less visible. To do this I created a separate function that should return a different value, to be placed as the alpha value, for each intensity value based upon its size compared to the max intensity value. When I run this though all scatter points receive the first opacity value I put into my function.
I can not spot the error and would appreciate if someone could cast there eye over it.
Section of code that generates plot and opacity function:
'''
Trial for opacity differentiation
'''
def OP(b):
for i in range(len(b)):
Imx = np.amax(b)
print(Imx)
if b[i] > .9*Imx:
return .9
elif b[i] <= .9*Imx:
return 0.1
else:
return 0
'''
3d Colour scatterplot of Intensity
'''
def hlkplt(filename):
h = np.linspace(0,4,9)
l = np.linspace(0,4,9)
k = np.linspace(0,4,9)
I = []
for j in range(len(h)):
for i in range(len(l)):
for n in range(len(k)):
IStot = Int2(filename,h[j],l[i],k[n])
p = IStot.real
I.append(p)
b = np.array(I)
hh, ll, kk = np.meshgrid(h,l,k)
cm = plt.get_cmap('RdYlGn')
fig = plt.figure()
ax3D = plt.axes(projection = '3d')
ax3D.set_xlabel('h plane')
ax3D.set_ylabel('l plane')
ax3D.set_zlabel('k plane')
p3d = ax3D.scatter(hh,ll,kk, s = 30, c = b,alpha =OP(b), marker ='o',label = filename)
plt.legend()
cbar = plt.colorbar(p3d)
cbar.set_label('Scattering Intensity of neutrons')
plt.show()
return
The Int2 function just produces a complex number which is turned real and placed into a list

How do I put a simple caption below my x axis in Matplotib?

I am trying to put a simple description of my plot right below the x axis with plt.text. Either there is not enough room or it's in my plot. Can someone help. Here is my code and what it looks like.
def econPlot1(plot1_data):
x = list(range(plot1_data.shape[0]))
y1 = plot1_data[:, 1]
# plotting the line 1 points
plt.plot(x, y1, label = "FFR")
# line 2 points
y2 = plot1_data[:, 2]
#fig = plt.figure()
plt.axis([0, 10, 0, 10])
t = ("This is a really long string that I'd rather have wrapped so that it "
"doesn't go outside of the figure, but if it's long enough it will go "
"off the top or bottom!")
plt.text(-1, 0, t, ha='center', rotation=0, wrap=True)
# plotting the line 2 points
plt.plot(x, y2, label = "Inflation")
plt.xlabel('time')
x_tick_indices = list(range(0, plot1_data.shape[0], 12))
x_tick_values = x_tick_indices
x_tick_labels = [plot1_data[i, 0] for i in x_tick_indices]
plt.xticks(x_tick_values, x_tick_labels, rotation ='vertical')
# Set a title of the current axes.
plt.title('FFR vs Inflation over time')
# show a legend on the plot
#plt.legend()
# Display a figure.
plt.show()
logging.debug('plot1 is created')
I managed to put your text at the bottom of the figure the following way:
import textwrap
# Operations on the source data
x = list(range(plot1_data.shape[0]))
y1 = plot1_data[:, 1]
y2 = plot1_data[:, 2]
x_tick_indices = list(range(0, plot1_data.shape[0], 12))
x_tick_values = x_tick_indices
x_tick_labels = [plot1_data[i, 0] for i in x_tick_indices]
t = "This is a really long string that I'd rather have wrapped so that it doesn't go "\
"outside of the figure, but if it's long enough it will go off the top or bottom!"
tt = textwrap.fill(t, width=70)
# Plotting
plt.plot(x, y1, label='FFR')
plt.plot(x, y2, label='Inflation')
plt.xlabel('Time')
plt.xticks(x_tick_values, x_tick_labels, rotation ='vertical')
plt.title('FFR vs Inflation over time')
plt.text(len(x) / 2, 0, tt, ha='center', va='top');
My experience indicates that plt.text does not support wrap parameter,
so I wrapped it using textwrap.fill.
I also didn't call plt.axis, relying on default limits for both x and y. If you need to set limits, do it rather only for y axis,
e.g. plt.ylim((0, 8)), but then you will have to adjust also y parameter
in plt.text.
For source data limited to 3 years (for each month in these 3 years and
Jan 1 the next year) I got the following result:

Distance between 2 user defined georeferenced grids in km

I have 2 variables 'Root zone' and 'Tree cover' both are geolocated (NetCDF) (which are basically grids with each grid having a specific value). The values in TC varies from 0 to 100. Each grid size is 0.25 degrees (might be helpful in understanding the distance).
My problem is "I want to calculate the distance of each TC value ranging between 70-100 and 30-70 (so each value of TC value greater than 30 at each lat and lon) from the points where nearest TC ranges between 0-30 (less than 30)."
What I want to do is create a 2-dimensional scatter plot with X-axis denoting the 'distance in km of 70-100 TC (and 30-70 TC) from 0-30 values', Y-axis denoting 'RZS of those 70-100 TC points (and 30-70 TC)'
#I read the files using xarray
deficit_annual = xr.open_dataset('Rootzone_CHIRPS_era5_2000-2015_annual_SA_masked.nc')
tc = xr.open_dataset('Treecover_MODIS_2000-2015_annual_SA_masked.nc')
fig, ax = plt.subplots(figsize = (8,8))
## year I am interested in
year = 2000
i = year - 2000
# Select the indices of the low- and high-valued points
# This will results in warnings here because of NaNs;
# the NaNs should be filtered out in the indices, since they will
# compare to False in all the comparisons, and thus not be
# indexed by 'low' and 'high'
low = (tc[i,:,:] <= 30) # Savanna
moderate = (tc[i,:,:] > 30) & (tc[i,:,:] < 70) #Transitional forest
high = (tc[i,:,:] >= 70) #Forest
# Get the coordinates for the low- and high-valued points,
# combine and transpose them to be in the correct format
y, x = np.where(low)
low_coords = np.array([x, y]).T
y, x = np.where(high)
high_coords = np.array([x, y]).T
y, x = np.where(moderate)
moderate_coords = np.array([x, y]).T
# We now calculate the distances between *all* low-valued points, and *all* high-valued points.
# This calculation scales as O^2, as does the memory cost (of the output),
# so be wary when using it with large input sizes.
from scipy.spatial.distance import cdist, pdist
distances = cdist(low_coords, moderate_coords, 'euclidean')
# Now find the minimum distance along the axis of the high-valued coords,
# which here is the second axis.
# Since we also want to find values corresponding to those minimum distances,
# we should use the `argmin` function instead of a normal `min` function.
indices = distances.argmin(axis=1)
mindistances = distances[np.arange(distances.shape[0]), indices]
minrzs = np.array(deficit_annual[i,:,:]).flatten()[indices]
plt.scatter(mindistances*25, minrzs, s = 60, alpha = 0.5, color = 'goldenrod', label = 'Trasitional Forest')
distances = cdist(low_coords, high_coords, 'euclidean')
# Now find the minimum distance along the axis of the high-valued coords,
# which here is the second axis.
# Since we also want to find values corresponding to those minimum distances,
# we should use the `argmin` function instead of a normal `min` function.
indices = distances.argmin(axis=1)
mindistances = distances[np.arange(distances.shape[0]), indices]
minrzs = np.array(deficit_annual[i,:,:]).flatten()[indices]
plt.scatter(mindistances*25, minrzs, s = 60, alpha = 1, color = 'green', label = 'Forest')
plt.xlabel('Distance from Savanna (km)', fontsize = '14')
plt.xticks(fontsize = '14')
plt.yticks(fontsize = '14')
plt.ylabel('Rootzone storage capacity (mm/year)', fontsize = '14')
plt.legend(fontsize = '14')
#plt.ylim((-10, 1100))
#plt.xlim((0, 30))
What I want is to know whether the code seems to have an error (as it is working now, but doesn't seem to work when I increase the 'high = (tc[i,:,:] >= 70 ` to 80 for year 2000. This makes me wonder if the code is correct or not.
Secondly, is it possible to define a 20 km buffer region of 'low = (tc[i,:,:] <= 30)'. What I mean is that the 'low' is defined only when a cluster of Tree cover values are below 30 and not by an individual pixel.
Some netCDF files are attached in the link below:
https://www.dropbox.com/sh/unm96q7sfto8y53/AAA7e12bs07XtpMiVFdML_PIa?dl=0
The graph I want is something like this (derived from the code above).
Thank you for your help.

Resources