Making graphs with PyLab, doesn't plot the first value? - python-3.x

Like the title says, I'm (learning to) plot with MatPlotLib/PyLab, and everything turns out fine, but the graph doesn't contain the first value in the list I'm plotting, and then causes all the values to be transformed one coordinate to the left. I've made a really simple program to illustrate this, and have provided an image of the final graph.
Windows 7, using NotePad++ but it makes the same result in IDLE as well.
Thanks for the help!
-Cory
from pylab import plot, show, axis
test = [1,2,1,2,1,2,1,2,1,2,1,2]
axis([1, 12, 0, 3])
plot(test, marker='o')
show()

You've set your axis to start from 1, it should be from 0. X-values begin from 0 by default.
from pylab import plot, show, axis
test = [1,2,1,2,1,2,1,2,1,2,1,2]
axis([0, 12, 0, 3])
plot(test, marker='o')
show()
However, if you from your first test value 1 to map for x=1, then provide the x values, like
from pylab import plot, show, axis
test = [1,2,1,2,1,2,1,2,1,2,1,2]
xvals = range(1, len(test)+1)
axis([1, 12, 0, 3])
plot(xvals, test, marker='o')
show()

Related

How to align twin-axis of datetimes over invisible original axis of floats/ints in imshow?

I would like to show datetimes as ticklabels on the x-axis of a plot via ax.imshow(). I first tried putting the limits (as datetime objects) into extent, but it appears that extent only accepts arguments of type <float/int>. So instead, I would like to create the original plot via ax.imshow(...), then make the x-axis invisible, then add in the correct xticks and xlim.
I found a similar problem solved using a different approach in this example, but I think my use-case is slightly different; I don't need to convert any time-stamps, but I do know the xlim of the data (in terms of datetime objects). Also, I do not think the suggested use of matplotlib.dates.date2num fits my use-case since some of the data is spaced less than one day apart, but date2num uses days as a base-unit.
I am stuck trying to make this work using my alternate approach; a simple mini-example is below.
import numpy as np
import datetime
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
def f(x, y):
return np.sqrt(np.square(x) + np.square(y))
## SAMPLE DATA
x = np.arange(10) ## elapsed minutes
y = np.square(x) ## arbitrary y-values
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
## DATETIMES FOR ALTERNATE AXIS
lower_dt = datetime.datetime(1999, 1, 1, 0, 0, 0)
# upper_dt = datetime.datetime(2001, 10, 31, 0, 0, 0)
upper_dt = datetime.datetime(1999, 1, 1, x.size-1, 0, 0)
## DO PLOT
fig, ax = plt.subplots()
ax.xaxis.set_visible(False)
# ax.xaxis.tick_top()
ax.imshow(
Z,
origin='lower',
cmap='Oranges',
norm=Normalize(vmin=np.nanmin(Z), vmax=np.nanmax(X)),
extent=(x[0], x[-1], y[0], y[-1]))
## CONVERT XTICKLABELS OF X-AXIS TO DATETIME
mirror_ax = ax.twiny()
# mirror_ax = ax.figure.add_subplot(ax.get_subplotspec(), frameon=False)
mirror_ax.set_xlim([lower_dt, upper_dt])
plt.show()
plt.close(fig)
The obtained plot can be seen here:
I notice that the xticks are shown at the top instead of the bottom of the plot - this is unwanted behavior; using ax.tick_top (commented out above) does not change this. Even worse, the x-axis limits are not retained. I realize I could manually change the xticklabels via ax.get_xticks() and ax.set_xticklabels(...), but I would prefer to leave that for date-formatters and date-locators via matplotlib.
How can I use the approach outlined above to create a "mirror/alternate" x-axis of datetime units such that this x-axis is the same size/orientation of the "original/invisible" x-axis of float/integer units?

Matplotlib not displaying all values

I am trying to display the following values in the form of a bar chart. However, I am only getting one value displayed (619,1). Below is the code which I used in an attempt to plot the below graph:
import matplotlib.pyplot as plt
plt.style.use('ggplot')
values= [1, 2, 3, 4, 5]
a = [619, 101, 815, 1361, 178]
plt.figure(figsize=(5, 5))
plt.bar(a, values)
plt.show()
The bar width is set to a default value of 0.8 so when your x-axis has such a large range, the bars are so skinny that they disappear.
The reason for the 0.8 is that bar charts are typically used for labelled categories, which are effectively spaced by 1 along the x-axis.
So you can set the width directly. (It's also possible to calculate a width, to make this more automatic, but then you need to decide about overlaps, etc.)
plt.figure(figsize=(5, 5))
plt.xlim(0, 1450)
plt.bar(a, values, width = 50)
It seems your data might be better suited for a horizontal bar plot (but don't take this too seriously as it may not have the right meaning at all), and if you want horizontal bars, you can do so like this:
plt.barh(values, a)

Adding a colorbar outside an image without shrinking it

I'm trying to plot a 3x3 subplots, the first line using imshow, and second and third are regular graphs. All the 3x3 plots share the same x-axis, so it's really important that they will be perfectly aligned (I didn't use sharey=true because I wanted the y-ticks). I was able to put the graphs legends outside the figure in the right (the legend is the same legend for the whole 3 figures in the same row) by using:
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
But I couldn't find how to put the colorbar of the first row above them, without shrinking the third plot in the first row. I was trying to use "make_axes_locatable":
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(powers_ax)
cax = divider.append_axes("right", size="5%", pad=1)
plt.colorbar(im, cax=cax)
Or "inset_axes":
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
axins = inset_axes(powers_ax, width="10%", height="100%", loc=5,
bbox_to_anchor=(0.5, 0, 1, 1), bbox_transform=powers_ax.transAxes)
plt.colorbar(im, cax=axins)
Or even this trick:
fig.colorbar(im2, ax=ax[0, :].ravel().tolist(), location='right', shrink=0.6)
But nothing gave me the result I watned.
Any ideas?
* EDIT *
As #ImportanceOfBeingErnest suggested, the solution was tweaking the first parameter in the bbox_to_anchor (from 0.5 to 1.15 in this case):
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
axins = inset_axes(powers_ax, width="5%", height="100%", loc=5,
bbox_to_anchor=(1.15, 0, 1, 1), bbox_transform=powers_ax.transAxes)
plt.colorbar(im2, cax=axins)

Using matplotlib to represent three variables in two dimensions with colors [duplicate]

I want to make a scatterplot (using matplotlib) where the points are shaded according to a third variable. I've got very close with this:
plt.scatter(w, M, c=p, marker='s')
where w and M are the data points and p is the variable I want to shade with respect to.
However I want to do it in greyscale rather than colour. Can anyone help?
There's no need to manually set the colors. Instead, specify a grayscale colormap...
import numpy as np
import matplotlib.pyplot as plt
# Generate data...
x = np.random.random(10)
y = np.random.random(10)
# Plot...
plt.scatter(x, y, c=y, s=500) # s is a size of marker
plt.gray()
plt.show()
Or, if you'd prefer a wider range of colormaps, you can also specify the cmap kwarg to scatter. To use the reversed version of any of these, just specify the "_r" version of any of them. E.g. gray_r instead of gray. There are several different grayscale colormaps pre-made (e.g. gray, gist_yarg, binary, etc).
import matplotlib.pyplot as plt
import numpy as np
# Generate data...
x = np.random.random(10)
y = np.random.random(10)
plt.scatter(x, y, c=y, s=500, cmap='gray')
plt.show()
In matplotlib grey colors can be given as a string of a numerical value between 0-1.
For example c = '0.1'
Then you can convert your third variable in a value inside this range and to use it to color your points.
In the following example I used the y position of the point as the value that determines the color:
from matplotlib import pyplot as plt
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [125, 32, 54, 253, 67, 87, 233, 56, 67]
color = [str(item/255.) for item in y]
plt.scatter(x, y, s=500, c=color)
plt.show()
Sometimes you may need to plot color precisely based on the x-value case. For example, you may have a dataframe with 3 types of variables and some data points. And you want to do following,
Plot points corresponding to Physical variable 'A' in RED.
Plot points corresponding to Physical variable 'B' in BLUE.
Plot points corresponding to Physical variable 'C' in GREEN.
In this case, you may have to write to short function to map the x-values to corresponding color names as a list and then pass on that list to the plt.scatter command.
x=['A','B','B','C','A','B']
y=[15,30,25,18,22,13]
# Function to map the colors as a list from the input list of x variables
def pltcolor(lst):
cols=[]
for l in lst:
if l=='A':
cols.append('red')
elif l=='B':
cols.append('blue')
else:
cols.append('green')
return cols
# Create the colors list using the function above
cols=pltcolor(x)
plt.scatter(x=x,y=y,s=500,c=cols) #Pass on the list created by the function here
plt.grid(True)
plt.show()

Making a histogram/barchart

i have a Pandas dataframe, which contains 6000 values ranging between 1 and 2500, i would like to create a chart that shows a predetermined x-axis, i.e. [1,2,4,8,16,32,64,128,256,512,more] and the a bar for each of these counts, i've been looking into the numpy.histogram, bit that does not let me choose the bin range (it estimates one) same goes for matplotlib.
The codes i've tried so far is,
plt.hist(df['cnt'],bins=[0,1,2,4,8,16,32,64,128,256,512])
plt.show()
np.histogram(df['cnt'])
And the plotting the np data, but i does not look like i want it.
I hope my question makes sense, else i will try to expand.
EDIT
when i run the
plt.hist(df['cnt'],bins=[0,1,2,4,8,16,32,64,128,256,512])
plt.show()
i get:
What i want:
Where the second one have been made in Excel using the data analysis histogram function. I hope this gives a better picture of what i would like to do.
I think you want a base-2 logarithmic scale on the xaxis.
You can do that by setting ax.set_xscale('log', basex=2)
You also then need to adjust the tick locations and formatting, which you can do with ax.xaxis.set_major_locator(ticker.FixedLocator(bins)) and ax.xaxis.set_major_formatter(ticker.ScalarFormatter()
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
fig, ax = plt.subplots(1)
# Some fake data
cnt = np.random.lognormal(0.5, 2.0, 6000)
# Define your bins
bins = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
# Plot the histogram
ax.hist(cnt, bins=bins)
# Set scale to base2 log
ax.set_xscale('log', basex=2)
# Set ticks and ticklabels using ticker
ax.xaxis.set_major_locator(ticker.FixedLocator(bins))
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
plt.show()

Resources