Related
The code below is supposed to update the graph (change the colors of the bar) depending on the ydata of on_click event. Some how, the colors do not chnage as supposed. Also, I'm using 'ax.clear()' to refresh the redraw the bars and the line every time the graph is clicked. Any idea what's wrong with this code?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import cm
import pandas as pd
# Use the following data for this assignment:
np.random.seed(12345)
df = pd.DataFrame([np.random.normal(32000,200000,3650),
np.random.normal(43000,100000,3650),
np.random.normal(43500,140000,3650),
np.random.normal(48000,70000,3650)],
index=[1992,1993,1994,1995])
fig, ax = plt.subplots()
#Plotting the Bar chart
mean = df.mean(axis = 1)
std = df.std(axis = 1)
n= df.shape[1]
yerr = 1.96*std/np.sqrt(3650)
plt.bar(range(df.shape[0]), mean, yerr = yerr, color = 'grey',capsize=10, alpha = 0.5)
plt.xticks(range(len(df.index)), df.index)
plt.title('Proportion of confidence interval lying below the threshold value')
plt.ylabel('Number of votes')
#Click on the graph to choose a value, the color of the bar change based on the yvalue
colourofbars = []
norm = None
cmap = plt.cm.get_cmap('RdYlBu')
dict = {mean[x]: yerr[x] for x in list(df.index)}
def onclick(event):
val = event.ydata
global colourofbars
global norm
#Defining the condition based on the ydata
for key,value in dict.items():
if val > (key+(value)):
colour = 0
colourofbars.append(colour)
elif val < (key-(value)):
colour = 1
colourofbars.append(colour)
elif ((key+(value))> val > (key-(value))):
colour = ((key+(value))-val)/((key+value)-(key-value))
colourofbars.append(colour)
ax.clear()
norm = matplotlib.colors.Normalize(vmin=min(colourofbars),vmax=max(colourofbars), clip=False)
#Plotting the colored bar chart
plt.bar(range(df.shape[0]), mean, yerr = yerr, capsize=10, alpha = 0.5, color=cmap(norm(colourofbars)))
plt.axhline(y=val,linewidth=1, color='k')
plt.gcf().canvas.draw_idle()
#Adding the colorbar legend
scalarmappaple = cm.ScalarMappable(norm=norm, cmap=cmap)
scalarmappaple.set_array(colourofbars)
plt.colorbar(scalarmappaple)
plt.gcf().canvas.mpl_connect('button_press_event', onclick)
fig.canvas.draw()
In Jupyter Notebook you have to add
%matplotlib notebook
in order to make the plot interactive (adding that line after import statements is fine).
With the above statement I get this plot:
If I click somewhere in the plot I get:
I have two values:
test1 = 0.75565
test2 = 0.77615
I am trying to plot a bar chart (using matlplotlib in jupyter notebook) with the x-axis as the the two test values and the y-axis as the resulting values but I keep getting a crazy plot with just one big box
here is the code I've tried:
plt.bar(test1, 1, width = 2, label = 'test1')
plt.bar(test2, 1, width = 2, label = 'test2')
As you can see in this example, you should define X and Y in two separated arrays, so you can do it like this :
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(2)
y = [0.75565,0.77615]
fig, ax = plt.subplots()
plt.bar(x, y)
# set your labels for the x axis here :
plt.xticks(x, ('test1', 'test2'))
plt.show()
the final plot would be like :
UPDATE
If you want to draw each bar with a different color, you should call the bar method multiple times and give it colors to draw, although it has default colors :
import matplotlib.pyplot as plt
import numpy as np
number_of_points = 2
x = np.arange(number_of_points)
y = [0.75565,0.77615]
fig, ax = plt.subplots()
for i in range(number_of_points):
plt.bar(x[i], y[i])
# set your labels for the x axis here :
plt.xticks(x, ('test1', 'test2'))
plt.show()
or you can do it even more better and choose the colors yourself :
import matplotlib.pyplot as plt
import numpy as np
number_of_points = 2
x = np.arange(number_of_points)
y = [0.75565,0.77615]
# choosing the colors and keeping them in a list
colors = ['g','b']
fig, ax = plt.subplots()
for i in range(number_of_points):
plt.bar(x[i], y[i],color = colors[i])
# set your labels for the x axis here :
plt.xticks(x, ('test1', 'test2'))
plt.show()
The main reason your plot is showing one large value is because you are setting a width for the columns that is greater than the distance between the explicit x values that you have set. Reduce the width to see the individual columns. The only advantage to doing it this way is if you need to set the x values (and y values) explicitly for some reason on a bar chart. Otherwise, the other answer is what you need for a "traditional bar chart".
import matplotlib.pyplot as plt
test1 = 0.75565
test2 = 0.77615
plt.bar(test1, 1, width = 0.01, label = 'test1')
plt.bar(test2, 1, width = 0.01, label = 'test2')
In the following code for each for loop i'm getting a single colorbar. But I want to represent the following data with a single colorbar.
`import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig = plt.figure()
ax= fig.add_subplot(111)
h_1 = np.load("./Result_2D/disorder.npy")
h = h_1[0:2]
print("h: ",h)
for k in range(len(h)):
h_val = round(h[k],1)
KL=np.load("./KL_%s.npy"%h_val)
print("KL: ",KL[0:5])
E = np.load("./E_%s.npy"%h_val)
print("E_shape: ",E[0:5])
W =np.load("./W_%s.npy"%h_val)
print("W: ",W[0:5])
sc= ax.scatter(E,W,c=KL,cmap='RdBu_r')
plt.colorbar(sc)`
here is some example code of how to print multiple scatter sets with the same single colorbar
pltrange = np.logspace(1, 2, num=20) #or use np.linspace, or provide a range of values (based on the limits of your data)
lbrange = pltrange[::2] #labels for colorbar
ax.scatter(x=stream['Dist'], y=stream['Depth'], s=50,
c=stream['Sand Concentration (mg/l)'],
cmap='rainbow', edgecolor='k', linewidths=1,
vmin=pltrange[0],vmax=pltrange[-1]) #note the vmin and vmax, do this for all scatter sets
cb = fig.colorbar(ax=ax, ticks=lbrange, pad=0.01) #display colorbar, keep outside loop
cb.ax.set_yticklabels(['{:.1f}'.format(i) for i in lbrange]) #format labels if desired
I realize it's not exactly formatted for your code but..it's the exact same principle and I'm posting this from bed :) so I think you could make the necessary adaptations
try this
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig = plt.figure()
ax= fig.add_subplot(111)
h_1 = np.load("./Result_2D/disorder.npy")
h = h_1[0:2]
print("h: ",h)
for k in range(len(h)):
h_val = round(h[k],1)
KL=np.load("./KL_%s.npy"%h_val)
print("KL: ",KL[0:5])
E = np.load("./E_%s.npy"%h_val)
print("E_shape: ",E[0:5])
W =np.load("./W_%s.npy"%h_val)
print("W: ",W[0:5])
sc= ax.scatter(E,W,c=KL,cmap='RdBu_r')
plt.colorbar(sc)
I am trying to create a color mesh plot but the data points and their corresponding colors appear too small.
My script is:
import pandas as pd
import numpy as np
from mpl_toolkits.basemap import Basemap, cm
import matplotlib.pyplot as plt
df = pd.read_csv('data.csv', usecols=[1,2,4])
df = df.apply(pd.to_numeric)
val_pivot_df = df.pivot(index='Latitude', columns='Longitude', values='Bin 1')
lons = val_pivot_df.columns.astype(float)
lats = val_pivot_df.index.astype(float)
fig, ax = plt.subplots(1, figsize=(8,8))
m = Basemap(projection='merc',
llcrnrlat=df.dropna().min().Latitude-5
, urcrnrlat=df.dropna().max().Latitude+5
, llcrnrlon=df.dropna().min().Longitude-5
, urcrnrlon=df.dropna().max().Longitude+5
, resolution='i', area_thresh=10000
)
m.drawcoastlines()
m.drawstates()
m.drawcountries()
m.fillcontinents(color='gray', lake_color='white')
m.drawmapboundary(fill_color='0.3')
x, y = np.meshgrid(lons,lats)
px,py = m(x,y)
data_values = val_pivot_df.values
masked_data = np.ma.masked_invalid(data_values)
cmap = plt.cm.viridis
m.pcolormesh(px, py, masked_data, vmin=0, vmax=8000)
m.colorbar()
plt.show()
I'm looking to get the markersize larger of each data point but I can't seem to find any documentation on how to do this for pcolormesh
There is no marker in a pcolormesh. The size of the colored areas in a pcolor plot is determined by the underlying grid. As an example, if the grid in x direction was [0,1,5,105], the last column would be 100 times larger in size than the first.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
x = [0,1,5,25,27,100]
y = [0,10,20,64,66,100]
X,Y = np.meshgrid(x,y)
Z = np.random.rand(len(y)-1, len(x)-1)
plt.pcolormesh(X,Y,Z)
plt.show()
I was wondering what the best way to make a y-label where each word in the label can be a different color.
The reason I would like this is because I will be making plots that will contain to curves (Electric Fields and Vector Potential Fields). These curves will be different colors and I would like to show this in the labels. The following is a simplified example, using a previous post (Matplotlib multiple colours in tick labels) to get close. This post does well for the x-axis, however it doesn't space/order the y-axis correctly.
Another post had a similar question (Partial coloring of text in matplotlib), but the first answer didn't seem to work at all anymore and the second answer makes you save the file as a .ps file.
My example code is
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker
ax = plt.subplot(111)
x = np.linspace(0,10,10)
y1 = x
y2 = x**2
ax.plot(x,y1,color='r',label='data1')
ax.plot(x,y2,color='b',label='data2')
ax.set_xticks([]) # empty xticklabels
ax.set_yticks([]) # empty xticklabels
# x-axis label
xbox1 = TextArea("Data1-x ", textprops=dict(color="r", size=15))
xbox2 = TextArea("and ", textprops=dict(color="k", size=15))
xbox3 = TextArea("Data2-x ", textprops=dict(color="b", size=15))
xbox = HPacker(children=[xbox1, xbox2, xbox3],
align="center", pad=0, sep=5)
anchored_xbox = AnchoredOffsetbox(loc=3, child=xbox, pad=0., frameon=False,
bbox_to_anchor=(0.3, -0.07),
bbox_transform=ax.transAxes, borderpad=0.)
# y-axis label
ybox1 = TextArea("Data1-y ", textprops=dict(color="r", size=15,rotation='vertical'))
ybox2 = TextArea("and ", textprops=dict(color="k", size=15,rotation='vertical'))
ybox3 = TextArea("Data2-y ", textprops=dict(color="b", size=15,rotation='vertical'))
ybox = VPacker(children=[ybox1, ybox2, ybox3],
align="center", pad=0, sep=5)
anchored_ybox = AnchoredOffsetbox(loc=8, child=ybox, pad=0., frameon=False,
bbox_to_anchor=(-0.08, 0.4),
bbox_transform=ax.transAxes, borderpad=0.)
ax.add_artist(anchored_xbox)
ax.add_artist(anchored_ybox)
plt.legend()
plt.show()
Thanks for the help!
You were almost there. You just need to specify the alignment of the text using ha='left',va='bottom'. (And flip the order of the TextArea objects passed to VPacker).
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker
ax = plt.subplot(111)
x = np.linspace(0,10,10)
y1 = x
y2 = x**2
ax.plot(x,y1,color='r',label='data1')
ax.plot(x,y2,color='b',label='data2')
ybox1 = TextArea("Data2-y ", textprops=dict(color="r", size=15,rotation=90,ha='left',va='bottom'))
ybox2 = TextArea("and ", textprops=dict(color="k", size=15,rotation=90,ha='left',va='bottom'))
ybox3 = TextArea("Data1-y ", textprops=dict(color="b", size=15,rotation=90,ha='left',va='bottom'))
ybox = VPacker(children=[ybox1, ybox2, ybox3],align="bottom", pad=0, sep=5)
anchored_ybox = AnchoredOffsetbox(loc=8, child=ybox, pad=0., frameon=False, bbox_to_anchor=(-0.08, 0.4),
bbox_transform=ax.transAxes, borderpad=0.)
ax.add_artist(anchored_ybox)
plt.legend()
plt.show()
Better yet, here is a function that makes the labels using an arbitrary list of strings and colors:
import numpy as np
import matplotlib.pyplot as plt
def multicolor_ylabel(ax,list_of_strings,list_of_colors,axis='x',anchorpad=0,**kw):
"""this function creates axes labels with multiple colors
ax specifies the axes object where the labels should be drawn
list_of_strings is a list of all of the text items
list_if_colors is a corresponding list of colors for the strings
axis='x', 'y', or 'both' and specifies which label(s) should be drawn"""
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker
# x-axis label
if axis=='x' or axis=='both':
boxes = [TextArea(text, textprops=dict(color=color, ha='left',va='bottom',**kw))
for text,color in zip(list_of_strings,list_of_colors) ]
xbox = HPacker(children=boxes,align="center",pad=0, sep=5)
anchored_xbox = AnchoredOffsetbox(loc=3, child=xbox, pad=anchorpad,frameon=False,bbox_to_anchor=(0.2, -0.09),
bbox_transform=ax.transAxes, borderpad=0.)
ax.add_artist(anchored_xbox)
# y-axis label
if axis=='y' or axis=='both':
boxes = [TextArea(text, textprops=dict(color=color, ha='left',va='bottom',rotation=90,**kw))
for text,color in zip(list_of_strings[::-1],list_of_colors) ]
ybox = VPacker(children=boxes,align="center", pad=0, sep=5)
anchored_ybox = AnchoredOffsetbox(loc=3, child=ybox, pad=anchorpad, frameon=False, bbox_to_anchor=(-0.10, 0.2),
bbox_transform=ax.transAxes, borderpad=0.)
ax.add_artist(anchored_ybox)
ax = plt.subplot(111)
x = np.linspace(0,10,1000)
y1 = np.sin(x)
y2 = np.sin(2*x)
ax.plot(x,y1,color='r')
ax.plot(x,y2,color='b')
multicolor_ylabel(ax,('Line1','and','Line2','with','extra','colors!'),('r','k','b','k','m','g'),axis='both',size=15,weight='bold')
plt.show()
It still takes some fiddling with the positions in the "bbox_to_anchor" keyword.