matplotlib plotting the wrong indices - python

I'm trying to plot both a line plot and scatter plot on the same figure. The scatter plot looks great, but the line is plotted at the incorrect indices. That is, the scatter plot data is along the correct indices, [0,4621], but the line plot is "bunched up" into indices [3750,4621].
plt.figure()
plt.plot(ii, values,
color='k', alpha=0.2)
plt.scatter(ii, scores,
color='g', s=20, alpha=0.3, marker="o")
plt.scatter(jj, scores[scores >= threshold],
color='r', s=20, alpha=0.7, marker="o")
plt.scatter(kk, labels[labels==1],
color='k', s=20, alpha=1.0, marker="+")
plt.axis([0, len(labels), 0, 1.1])
plt.title(relativePath)
plt.show()

The issue is the axes setting plt.axis([0, len(labels), 0, 1.1]) because values does not fit in the y-axis bounds. So normalizing the values list keeps it within the specified bounds [0,1.1]. This is done with norm_values = [float(v)/max(values) for v in values].

Related

How to plot bars next to each other?

I have a histogram with 4 different objects on each bin, that now are stacked on top of each other. Instead, I need to plot the different objects side by side within the same histogram bin (similar to the top left plot in https://matplotlib.org/3.1.1/gallery/statistics/histogram_multihist.html):
bins=np.logspace(np.log10(0.01),np.log10(20), 11)
plt.hist(a[nosfr]/1e+11, bins, color='red', fill=True, linewidth=2, density=True, histtype='bar', edgecolor='k')
plt.hist(a[highsfr]/1e+11, bins, color='orange', fill=True, linewidth=2, density=True, histtype='bar', edgecolor='k')
plt.hist(b[mynosfr]/1e+11, bins, color='blue', edgecolor='k', fill=True, linewidth=2, density=True, alpha=0.7, histtype='bar')
plt.hist(b[myhighsfr]/1e+11, bins, color='cyan', edgecolor='k', fill=True, linewidth=2, density=True, alpha=0.7, histtype='bar')
plt.xscale('log')
plt.xlim(2e-2, 2e+1)
[nosfr], [highsfr] etc. draw objects with different criteria within the same sample (a and b). All the examples I've looked at are slightly different from what I need, and I can't find the right way. Thanks!
Call plot method from your data frame with kind parameter set to bar.
x = np.random.random((10, 4))
df = pd.DataFrame(x, columns=['a', 'b', 'c', 'd'])
df.plot(kind='bar')
This is the result:

No handles with labels found to put in legend

I'm trying to create a parallelogram in PyPlot. I'm not up to drawing the parallelogram--first I'm putting in the vector arrows--using the following code:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
plt.axis([-5,5,-5,5])
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
plt.grid()
plt.arrow(0,0, 3,1, head_width=0.2, color='r', length_includes_head=True, label='u')
plt.arrow(0,0, 1,3, head_width=0.2, color='r', length_includes_head=True, label='v')
plt.arrow(0,0, 4,4, head_width=0.2, color='r', length_includes_head=True, label='u+v')
plt.legend()
This returns the following error:
No handles with labels found to put in legend.
I'm not sure why, because, based on the documentation for plt.arrow(), label is an acceptable kwarg, and plt.legend() should ostensibly be reading that. The rest of the figure draws fine; it's just missing the legend.
It might be late but for anyone with the same issue the solution is using the method legend() for the corresponding ax not as for plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
plt.axis([-5,5,-5,5])
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
plt.grid()
plt.arrow(0,0, 3,1, head_width=0.2, color='r', length_includes_head=True, label='u')
plt.arrow(0,0, 1,3, head_width=0.2, color='r', length_includes_head=True, label='v')
plt.arrow(0,0, 4,4, head_width=0.2, color='r', length_includes_head=True, label='u+v')
ax.legend()
You can explicitly define the elements in the legend.
For full control of which artists have a legend entry, it is possible to pass an iterable of legend artists followed by an iterable of legend labels respectively. Reference
Example:
arr1 = plt.arrow(0,0, 3,1, head_width=0.2, color='r', length_includes_head=True)
arr2 = plt.arrow(0,0, 1,3, head_width=0.2, color='g', length_includes_head=True)
arr3 = plt.arrow(0,0, 4,4, head_width=0.2, color='b', length_includes_head=True)
plt.xlim(0,5)
plt.ylim(0,5)
plt.legend([arr1, arr2, arr3], ['u','v','u+v'])
The error is thrown because you haven't specified the label text
Either do something like this
plt.hist([x01, x02,x03], color=["lightcoral","lightskyblue","slategrey"], stacked=True,
label=['Supressed','Active','Resolved'])
plt.legend()
Or
Do not use plt.legend() if you haven't specified the label text as in the following WRONG example:
plt.hist([x01])
plt.legend()
The above will throw the same error, so either remove legend function or provide what it needs -> label.
Side note: Here x01 is just a list of number for which I am creating a histogram, in the first example they are three list of numbers to create stacked bar chart
The bottom line is this error is thrown because of not specifying legend text and calling/initializing a legend
I had this error when using labels which started with an underscore
plt.plot(x, y, label = '_bad_name')
Removing the front underscore from the labels solved the issue
Assuming you have 2 plots ax and ax2, we can:
get the labels from each y-axis via ax.get_label()
.legend allows an array to be ingested
fig.legend([ax.get_ylabel(), ax2.get_ylabel()], loc='upper right')
I had this same issue and solved it with an understanding that .legend() function has to be after all the instructions that deal with the label attribute. This includes both plt and ax.
So moving ax.legend(*) as the last command.
I hope this helps you too.
Change
ax.plot(-trip_df.stop_lat, -trip_df.stop_lon, label = trip_id)
plt.legend()
to
ax.plot(-trip_df.stop_lat, -trip_df.stop_lon, label = trip_id)
ax.legend()
plt.legend()
I face similar problem like No handles with labels found to put in legend.
First My code look like
figure, axis = pyplot.subplots(nrows=1,ncols=2, figsize=(15, 6), tight_layout=True)
axis[0].legend(title='Country', title_fontsize = 12) #this line
axis[0].pie(x=piechart_result['value_eur'],labels=piechart_result['short_name'])
axis[1].pie(x=piechart_result['value_eur'],labels=piechart_result['short_name')
pyplot.show()
Then I changed to
figure, axis = pyplot.subplots(nrows=1,ncols=2, figsize=(15, 6), tight_layout=True)
axis[0].pie(x=piechart_result['value_eur'],labels=piechart_result['short_name'])
axis[0].legend(title='Country', title_fontsize = 12) # this line
axis[1].pie(x=piechart_result['value_eur'],labels=piechart_result['short_name')
pyplot.show()
this work for me in colab notebook

Subplot problem: how to plot for each plot a histogram by categorical values?

I have a DataFrame with three numerical variables Porosity, Perm and AI. I would like to make a subplot and in each plot, I would like the histogram of the three variables, by a categorical variable 'Facies'. Facies can take only two values: Sand and Shale.
In summary, each subplot needs a histogram and each histogram must be drawn based in the categorical variable Facies, to make a comparison between facies.
So far, I can make it work, but I cannot add the axis title to each subplot.
plt.subplot(311)
plt.hist(df_sd['Porosity'].values, label='Sand', bins=30, alpha=0.6)
plt.hist(df_sh['Porosity'].values, label='Shale', bins=30, alpha=0.6)
ax.set(xlabel='Porosity (fraction)', ylabel='Density', title='Porosity
Histogram')
plt.legend()
plt.subplot(312)
plt.hist(df_sd['log10Perm'].values, label='Sand', bins=30, alpha=0.6,)
plt.hist(df_sh['log10Perm'].values, label='Shale', bins=30, alpha=0.6)
ax.set(xlabel='Permeability (mD)', ylabel='Density', title='Permeability
Histogram')
plt.legend()
plt.subplot(313)
plt.hist(df_sd['AI'].values, label='Sand', bins=30, alpha=0.6)
plt.hist(df_sh['AI'].values, label='Shale', bins=30, alpha=0.6)
ax.set(xlabel='AI (units)', ylabel='Density', title='Acoustic Impedance
Histogram')
plt.legend()
plt.subplots_adjust(left=0.0, bottom=0.0, right=1.5, top=3.5, wspace=0.1,
hspace=0.2);
#I have tried with:
fig, axs = plt.subplots(2, 1)
but when I code
axs[0].hist(df_sd['Porosity'].values, label='Sand', bins=30, alpha=0.6)
axs[0].hist(df_sd['Porosity'].values, label='Shale', bins=30, alpha=0.6)
#But the histogram for shale overrides the histogram for Sand.
I would like to have this result but with both x and y axis with label names. Furthermore, it would be helpful to have a title for each subplot.
I just did a subplot with contours, but I think the framework will be very similar:
fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax, extend in zip(axs.ravel(), extends):
cs = ax.contourf(X, Y, Z, levels, cmap=cmap, extend=extend, origin=origin)
fig.colorbar(cs, ax=ax, shrink=0.9)
ax.set_title("extend = %s" % extend)
ax.locator_params(nbins=4)
plt.show()
I think the main point to note (and this I learned from the link below) is their use of zip(axs.ravel()) in the for loop to establish each ax and then plot what you wish on that ax. I'm fairly certain you can adapt this for your uses.
The full example is available at: https://matplotlib.org/gallery/images_contours_and_fields/contourf_demo.html#sphx-glr-gallery-images-contours-and-fields-contourf-demo-py
I have found an answer:
fig = plt.figure()
ax = fig.add_subplot(111)
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax2 = fig.add_subplot(313)
plt.subplot(311)
ax1.hist(df_sd['Porosity'].values, label='Sand', bins=30, alpha=0.6)
ax1.hist(df_sh['Porosity'].values, label='Shale', bins=30, alpha=0.6)
ax1.set(xlabel='Porosity (fraction)', ylabel='Density', title='Porosity Histogram')
ax1.legend()

Scatter plot with infinitesimal point size in Python

Is it possible to do scatter plot in python, having points have minimal size of 1 pixel at given scale? I.e. points should not scale as I scale the plot and have size of 1 pixel always.
In pyplot
plt.scatter(d3_transformed[:,0], d3_transformed[:,1], s=1)
I still get fat point like this
You can change the marker to a point by setting marker='.', and then further reduce its size by removing the outline using linewidths=0. Note that markeredgewidth does not work with scatter.
Consider this example. As you can see, the last line of points plotted (marker='.', s=1, linewidths=0) gives the smallest markers:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1)
x = np.linspace(0, 10, 100)
ax.scatter(x, np.ones_like(x)+0, marker='o', s=1, color='k')
ax.scatter(x, np.ones_like(x)+1, marker='o', s=1, color='k', linewidths=0)
ax.scatter(x, np.ones_like(x)+2, marker='.', s=1, color='k')
ax.scatter(x, np.ones_like(x)+3, marker='.', s=1, color='k', linewidths=0)
plt.show()
In scatterplot, the points have marker which is a symbol, like circle, and this symbol has also a border. I think the border is on by default. Try to turn off the bored, like set its width to 0.
http://matplotlib.org/api/lines_api.html#matplotlib.lines.Line2D.set_markeredgewidth

Scatter plot with two data sets

The following code plots two lines. Instead I need dots without lines:
plt.plot(y1, marker='o', color='b')
plt.plot(y2, marker='o', color='r')
plt.show()
What should I change to get proper result?
You could use plt.scatter to get a scatter plot.
import matplotlib.pylot as plt
plt.scatter(x, y1)
plt.scatter(x, y2)
plt.show()
You would set x to be a list containing the corresponding x axis values for your series. For instance, if your data start from x=0 and go up by one, you could use x = range(len(y1)) as your x axis series.
I would do the following:
plt.plot(y1, marker='o', linestyle=None, color='b')
plt.plot(y2, marker='o', linestyle=None, color='r')
plt.show()
EDIT: the linestyle=None raises an Error. You can use linestyle='' or directly:
plt.plot(y1,'bo')
plt.plot(y2,'ro')
plt.show()
should work.

Categories

Resources