plotting vertical bars instead of points, plot_date - python

I want to plot vertical bars instead of points. The actual data I have are irregularly spaced, so this will help visualize gaps more easily.
When I try to plot it, the best I can do are points, which don't increase in size as you zoom in!
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
YY = range(10)
plt.plot_date(XX,YY,'o')
Any ideas on how I can make taller/bigger (but not wider!) points?

You can use ax.vlines to plot a collection of vertical lines.
You can adjust ymin and ymax to suit your data.
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
plt.vlines(XX, ymin=0, ymax=1, linewidth=5)
plt.show()

Did you mean bars like this?
And here is the code:
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
YY = range(10)
plt.plot_date(XX,YY,'|')
plt.show()
You can change the shape of your plot by changing the third argument you pass in the plt.plot_date function.
In your code you are passing an 'o' that is why you get a dot. Here i pass bar to plot bar.

Related

Change y axis range of a secondary axis in python Matplotlib

I have two plots overlaid on each other generated by the following code:
import matplotlib.pyplot as plt
import pandas as pd
width=.5
t=pd.DataFrame({'bars':[3.4,3.1,5.1,5.1,3.8,4.2,5.2,4.0,3.6],'lines':[2.4,2.2,2.4,2.1,2.0,2.1,1.9,1.8,1.9]})
t['bars'].plot(kind='bar',width=width)
t['lines'].plot(secondary_y=True, color='red')
ax=plt.gca()
plt.xlim([-width,len(t['bars'])-width])
ax.set_xticklabels(('1','2','3','4','5','6','7','8','9'))
plt.show()
I want to be able to scale the range of the second y axis to go from 0.0 to 2.5 (instead of 1.8 to 2.4) in steps of .5. How can I define this without changing the bar chart at all?
Pandas returns the axis on which it plots when you call the plot function. Just save that axis and modify the limits using the object oriented approach.
import matplotlib.pyplot as plt
import pandas as pd
width=.5
t=pd.DataFrame({'bars':[3.4,3.1,5.1,5.1,3.8,4.2,5.2,4.0,3.6],'lines':[2.4,2.2,2.4,2.1,2.0,2.1,1.9,1.8,1.9]})
ax1 = t['bars'].plot(kind='bar',width=width)
ax2 = t['lines'].plot(secondary_y=True, color='red')
ax2.set_ylim(0, 2.5)
ax1.set_xlim([-width,len(t['bars'])-width])
ax1.set_xticklabels(('1','2','3','4','5','6','7','8','9'))
plt.show()

How to add vertical grid lines in a grouped boxplot in Seaborn?

I want to create a grouped boxplot with vertical grid lines in seaborn, i.e., at each tick, there should be a vertical line, just as in a regular scatter plot.
Some example code:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import numpy.random as rnd
some_x=[1,2,3,7,9,10,11,12,15,18]
data_for_each_x=[]
for i in range(0, len(some_x)):
rand_int=rnd.randint(10,30)
data_for_each_x.append([np.random.randn(rand_int)])
sns.set()
sns.boxplot(data=data_for_each_x, showfliers=False)
plt.show()
How it looks:
If I understood you correctly, you want the vertical white grid lines instead of the horizontal lines which you are getting currently. This is one way to do so:
Create an axis object ax and then assign this to the sns.boxplot. Then you can choose which grid lines to show by using a boolean argument to ax.xaxis.grid and ax.yaxis.grid. Since you want the vertical grid lines, turn off the y-grid (False) and turn on the x-grid (True).
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import numpy.random as rnd
fig, ax = plt.subplots() # define the axis object here
some_x=[1,2,3,7,9,10,11,12,15,18]
data_for_each_x=[]
for i in range(0, len(some_x)):
rand_int=rnd.randint(10,30)
data_for_each_x.append([np.random.randn(rand_int)])
sns.set()
sns.boxplot(data=data_for_each_x, showfliers=False, ax=ax) # pass the ax object here
ax.yaxis.grid(False) # Hide the horizontal gridlines
ax.xaxis.grid(True) # Show the vertical gridlines
In case you want to show both x and y grids, use ax.grid(True)

How to fix the limits of color scale in matplotlib?

I am implementing a loop to produce contour plots using the function contourf in matplotlib. The objective of the study is to find out any moving patterns in the area. But, the plots produced are having different color scales. Some of them have -4 to 4 while others have -1.5 to 9.0 and so on which renders the interpretation pointless. How can I fix this color scale to -5.0 to 9.0?
Also, when I try to export the plots number of colorbars increases in each plot. For example the second plot in the loop has 2 colorbars and fifth plot has 5 colorbars and so on.
What I've done so far:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from numpy import linspace
from numpy import meshgrid
i=0
while i<len(inputdata):
map = Basemap(projection='cyl', llcrnrlat=5.125, llcrnrlon=60.125, urcrnrlat=34.875, urcrnrlon=94.875)
data = np.array(inputdata[i])
x = linspace(map.llcrnrx, map.urcrnrx, data.shape[1])
y = linspace(map.llcrnry, map.urcrnry, data.shape[0])
xx, yy = meshgrid(x, y)
map.contourf(xx, yy, data, cmap = 'summer_r')
plt.colormap()
plt.savefig('filename.jpg',dpi=300)
i+=1
In order to change the limits of the colorbar, you can call plt.clim() before you call plt.colorbar and specify the range manually:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from numpy import linspace
from numpy import meshgrid
i=0
while i<len(inputdata):
map = Basemap(projection='cyl', llcrnrlat=5.125, llcrnrlon=60.125, urcrnrlat=34.875, urcrnrlon=94.875)
data = np.array(inputdata[i])
x = linspace(map.llcrnrx, map.urcrnrx, data.shape[1])
y = linspace(map.llcrnry, map.urcrnry, data.shape[0])
xx, yy = meshgrid(x, y)
map.contourf(xx, yy, data, cmap = 'summer_r')
plt.clim(-5, 9) # manually setup the range of the colorscale and colorbar
plt.colormap()
plt.savefig('filename.jpg',dpi=300)
plt.clf()
i+=1
You also may want to clear the figure after you have saved it to avoid multiple colorbars appearing using plt.clf()

Manually draw log-spaced tick marks and labels in matplotlib

I frequently find myself working in log units for my plots, for example taking np.log10(x) of data before binning it or creating contour plots. The problem is, when I then want to make the plots presentable, the axes are in ugly log units, and the tick marks are evenly spaced.
If I let matplotlib do all the conversions, i.e. by setting ax.set_xaxis('log') then I get very nice looking axes, however I can't do that to my data since it is e.g. already binned in log units. I could manually change the tick labels, but that wouldn't make the tick spacing logarithmic. I suppose I could also go and manually specify the position of every minor tick such it had log spacing, but is that the only way to achieve this? That is a bit tedious so it would be nice if there is a better way.
For concreteness, here is a plot:
I want to have the tick labels as 10^x and 10^y (so '1' is '10', 2 is '100' etc.), and I want the minor ticks to be drawn as ax.set_xaxis('log') would draw them.
Edit: For further concreteness, suppose the plot is generated from an image, like this:
import matplotlib.pyplot as plt
import scipy.misc
img = scipy.misc.face()
x_range = [-5,3] # log10 units
y_range = [-55, -45] # log10 units
p = plt.imshow(img,extent=x_range+y_range)
plt.show()
and all we want to do is change the axes appearance as I have described.
Edit 2: Ok, ImportanceOfBeingErnest's answer is very clever but it is a bit more specific to images than I wanted. I have another example, of binned data this time. Perhaps their technique still works on this, though it is not clear to me if that is the case.
import numpy as np
import pandas as pd
import datashader as ds
from matplotlib import pyplot as plt
import scipy.stats as sps
v1 = sps.lognorm(loc=0, scale=3, s=0.8)
v2 = sps.lognorm(loc=0, scale=1, s=0.8)
x = np.log10(v1.rvs(100000))
y = np.log10(v2.rvs(100000))
x_range=[np.min(x),np.max(x)]
y_range=[np.min(y),np.max(y)]
df = pd.DataFrame.from_dict({"x": x, "y": y})
#------ Aggregate the data ------
cvs = ds.Canvas(plot_width=30, plot_height=30, x_range=x_range, y_range=y_range)
agg = cvs.points(df, 'x', 'y')
# Create contour plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.contourf(agg, extent=x_range+y_range)
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()
The general answer to this question is probably given in this post:
Can I mimic a log scale of an axis in matplotlib without transforming the associated data?
However here an easy option might be to scale the content of the axes and then set the axes to a log scale.
A. image
You may plot your image on a logarithmic scale but make all pixels the same size in log units. Unfortunately imshow does not allow for such kind of image (any more), but one may use pcolormesh for that purpose.
import numpy as np
import matplotlib.pyplot as plt
import scipy.misc
img = scipy.misc.face()
extx = [-5,3] # log10 units
exty = [-45, -55] # log10 units
x = np.logspace(extx[0],extx[-1],img.shape[1]+1)
y = np.logspace(exty[0],exty[-1],img.shape[0]+1)
X,Y = np.meshgrid(x,y)
c = img.reshape((img.shape[0]*img.shape[1],img.shape[2]))/255.0
m = plt.pcolormesh(X,Y,X[:-1,:-1], color=c, linewidth=0)
m.set_array(None)
plt.gca().set_xscale("log")
plt.gca().set_yscale("log")
plt.show()
B. contour
The same concept can be used for a contour plot.
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(-1.1,1.9)
y = np.linspace(-1.4,1.55)
X,Y = np.meshgrid(x,y)
agg = np.exp(-(X**2+Y**2)*2)
fig, ax = plt.subplots()
plt.gca().set_xscale("log")
plt.gca().set_yscale("log")
exp = lambda x: 10.**(np.array(x))
cf = ax.contourf(exp(X), exp(Y),agg, extent=exp([x.min(),x.max(),y.min(),y.max()]))
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()

horizontal plot in python

I am looking for a plot that is rotated 90 degree in clockwise directions. An similar example of such plot is "hist(x, orientation='horizontal')". Is there any way to achieve similar orientation.
#Make horizontal plots.
import random
import matplotlib.pyplot as plt
x = random.sample(range(1000), 100)
x
plt.plot(x) #orientation='horizontal'
plt.show()
plt.plot(x) plots your x values automatically against the y-axis. In order to get a rotated plot you have to plot your x values against the x axis. So you'll need a to make vector for the y-axis, which has the same length as your sample.
import random
import matplotlib.pyplot as plt
import numpy as np
x=random.sample(1000)
y=np.arange(1000)
plt.plot(x,y)
Using plt.plot(x), matplotlib takes your x-values as its y-values and generates a vector for the x axis automatically.

Categories