Renaming a single plot i a sequence of 5 plots - python-3.x

I have the 5 plots generated by the code below. What i need is a quick way to only rename the title of the 3th plot from dataset(100,33) to dataset-trial. Whats the fasted way to do that?
import numpy as np
import matplotlib.pyplot as plt
ratios = [(100, 2), (100, 20),(100,33),(100, 40), (100, 80)]
plt.figure(figsize = (20,6))
for j,i in enumerate(ratios):
plt.subplot(1, 5, j+1)
X_p=np.random.normal(0,0.05,size=(i[0],2))
X_n=np.random.normal(0.13,0.02,size=(i[1],2))
y_p=np.array([1]*i[0]).reshape(-1,1)
y_n=np.array([0]*i[1]).reshape(-1,1)
X=np.vstack((X_p,X_n))
y=np.vstack((y_p,y_n))
plt.title("dataset" + str(j+1) +str(i))
plt.scatter(X_p[:,0],X_p[:,1])
plt.scatter(X_n[:,0],X_n[:,1],color='red')
plt.show()
Thanks

Related

Insert a png image in a matplotlib figure

I'm trying to insert a png image in matplotlib figure (ref)
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.figure import Figure
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
ax = plt.subplot(111)
ax.plot(
[1, 2, 3], [1, 2, 3],
'go-',
label='line 1',
linewidth=2
)
arr_img = plt.imread("stinkbug.png")
im = OffsetImage(arr_img)
ab = AnnotationBbox(im, (1, 0), xycoords='axes fraction')
ax.add_artist(ab)
plt.show()
Inset image:
Output obtained:
I'd like to know how to resize the image that has to be inserted to avoid overlaps.
EDIT:
Saving the figure
ax.figure.savefig("output.svg", transparent=True, dpi=600, bbox_inches="tight")
You can zoom the image and the set the box alignment to the lower right corner (0,1) plus some extra for the margins:
im = OffsetImage(arr_img, zoom=.45)
ab = AnnotationBbox(im, (1, 0), xycoords='axes fraction', box_alignment=(1.1,-0.1))
You may also want to use data coordinates, which is the default, and use the default box_alignment to the center, e.g. ab = AnnotationBbox(im, (2.6, 1.45)). See the xycoords parameter doc for more information about various coordinate options.

Bar missing while plotting using Matplotlib's Twinx

I'm using matplotlib.axes.Axes.twinx to have a shared x-axis in matplotlib for both . I dont know why instead of 13 bars to be plotted, only 12 of them are getting plotted.
Link of Data set
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
dataFrame=pd.read_csv("NEM.csv",sep=',')
dataFrame['ratio']=dataFrame['Expert']/dataFrame['Novice']
fig, ax1 = plt.subplots(figsize=(9, 6))
ax1.set_title('N-E Analysis')
xticklabels=dataFrame['Task'].tolist()
ax1.plot('Novice', data=dataFrame, marker='', color='dodgerblue', linewidth=2,label='Novice',zorder=100)
ax1.plot('Expert', data=dataFrame, marker='', color='darkorange', linewidth=2,label='Expert',zorder=200)
plt.ylim(0,120)
ax2 = ax1.twinx()
ax2.bar('Task','ratio', data=dataFrame, color='gray',width=0.35,label='NE',zorder=0)
ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False)
ax1.spines['left'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax1.set_xticklabels(xticklabels, rotation = 45, ha="right")
ax1.yaxis.grid()
ax1.tick_params(left='off',bottom='off')
ax2.tick_params(right='off')
plt.ylim(0,12)
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
p=ax1.legend(h2+h1, l2+l1, loc=2,frameon=False)
fig.tight_layout()
plt.show()
When using plots, it could be good practice to say explicitily how many bars or points you are going to plot. For instance, you can create an x-axis this way:
x_axis = np.arange(len(dataFrame[Task].tolist())
then:
ax1.plot(x_axis, dataFrame['Novice'].tolist(), ...)
after that you rename the xticklabels like this:
ax1.set_xticks(x_axis)
ax1.set_xticklabels(dataFrame[Task].tolist())
Do the same with the bar graph:
ax2.bar(x_axis, dataFrame['Ratio'].tolist(), ...)
This should do the trick.
Hope it helps.

How to visualize a list of strings on a colorbar in matplotlib

I have a dataset like
x = 3,4,6,77,3
y = 8,5,2,5,5
labels = "null","exit","power","smile","null"
Then I use
from matplotlib import pyplot as plt
plt.scatter(x,y)
colorbar = plt.colorbar(labels)
plt.show()
to make a scatter plot, but cannot make colorbar showing labels as its colors.
How to get this?
I'm not sure, if it's a good idea to do that for scatter plots in general (you have the same description for different data points, maybe just use some legend here?), but I guess a specific solution to what you have in mind, might be the following:
from matplotlib import pyplot as plt
# Data
x = [3, 4, 6, 77, 3]
y = [8, 5, 2, 5, 5]
labels = ('null', 'exit', 'power', 'smile', 'null')
# Customize colormap and scatter plot
cm = plt.cm.get_cmap('hsv')
sc = plt.scatter(x, y, c=range(5), cmap=cm)
cbar = plt.colorbar(sc, ticks=range(5))
cbar.ax.set_yticklabels(labels)
plt.show()
This will result in such an output:
The code combines this Matplotlib demo and this SO answer.
Hope that helps!
EDIT: Incorporating the comments, I can only think of some kind of label color dictionary, generating a custom colormap from the colors, and before plotting explicitly grabbing the proper color indices from the labels.
Here's the updated code (I added some additional colors and data points to check scalability):
from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
# Color information; create custom colormap
label_color_dict = {'null': '#FF0000',
'exit': '#00FF00',
'power': '#0000FF',
'smile': '#FF00FF',
'addon': '#AAAAAA',
'addon2': '#444444'}
all_labels = list(label_color_dict.keys())
all_colors = list(label_color_dict.values())
n_colors = len(all_colors)
cm = LinearSegmentedColormap.from_list('custom_colormap', all_colors, N=n_colors)
# Data
x = [3, 4, 6, 77, 3, 10, 40]
y = [8, 5, 2, 5, 5, 4, 7]
labels = ('null', 'exit', 'power', 'smile', 'null', 'addon', 'addon2')
# Get indices from color list for given labels
color_idx = [all_colors.index(label_color_dict[label]) for label in labels]
# Customize colorbar and plot
sc = plt.scatter(x, y, c=color_idx, cmap=cm)
c_ticks = np.arange(n_colors) * (n_colors / (n_colors + 1)) + (2 / n_colors)
cbar = plt.colorbar(sc, ticks=c_ticks)
cbar.ax.set_yticklabels(all_labels)
plt.show()
And, the new output:
Finding the correct middle point of each color segment is (still) not good, but I'll leave this optimization to you.

axis limit and sharex in matplotlib

I would like to show two images like these.
import matplotlib as plt
import numpy as np
fig, axes = plt.subplots(2, 1, )
axes[0].imshow(np.random.random((3, 3)))
axes[1].imshow(np.random.random((6, 3)))
Then, I tried sharex=True, which unexpectedly changed the ylim of the two plots. Why?? Is it possible to align the plots without changing the y axis limits?
fig, axes = plt.subplots(2, 1, sharex=True)
axes[0].imshow(np.random.random((3, 3)))
axes[1].imshow(np.random.random((6, 3)))
I use python 3.5.2 and matplotlib 1.5.1.
By default imshow axes have an equal aspect ratio. To preserve this, the limits are changed.
You have two options:
a) Dispense with equal aspect
Set the aspect to "auto". This allows the subplots to take the available space and share their axis.
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(2, 1,sharex=True )
axes[0].imshow(np.random.random((3, 3)), aspect="auto")
axes[1].imshow(np.random.random((6, 3)), aspect="auto")
plt.show()
b) Adjust the figure size or spacings
You can adjust the figure size or the spacings such that the axes actually match. You'd then also need to set the height_ratios according to the image dimensions.
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(2, 1,sharex=True, figsize=(3,5),
gridspec_kw={"height_ratios":[1,2]} )
plt.subplots_adjust(top=0.9, bottom=0.1, left=0.295, right=0.705, hspace=0.2)
axes[0].imshow(np.random.random((3, 3)))
axes[1].imshow(np.random.random((6, 3)))
plt.show()
This method either involves some trial and error or a sophisticated calculation, as e.g. in this answer.

How can I add a normal distribution curve to multiple histograms?

With the following code I create four histograms:
import numpy as np
import pandas as pd
data = pd.DataFrame(np.random.normal((1, 2, 3 , 4), size=(100, 4)))
data.hist(bins=10)
I want the histograms to look like this:
I know how to make it one graph at the time, see here
But how can I do it for multiple histograms without specifying each single one? Ideally I could use 'pd.scatter_matrix'.
Plot each histogram seperately and do the fit to each histogram as in the example you linked or take a look at the hist api example here. Essentially what should be done is
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
for ax in [ax1, ax2, ax3, ax4]:
n, bins, patches = ax.hist(**your_data_here**, 50, normed=1, facecolor='green', alpha=0.75)
bincenters = 0.5*(bins[1:]+bins[:-1])
y = mlab.normpdf( bincenters, mu, sigma)
l = ax.plot(bincenters, y, 'r--', linewidth=1)
plt.show()

Resources