matplotlib: plot or scatter without line through marker - matplotlib

is there a simple way to have scatter() plots (or just plots) with data points shown by some marker and connected by lines, but, when markerfacecolor='none' (or facecolor=none) have the line not shown within the area of the marker.
E.g.:
xx = arange(0.0,10.0,0.5)
yy = sin(xx)
plt.plot(xx,yy,'k-',marker='o',markerfacecolor='none')
results in the following figure.
But I would like the lines connecting data points to start not from the center of each marker but from its borders.

Related

Connect lines in plot

I have a plot with the numbers 1-9 on the y axis. I have a data frame (gaze data) with numbers in this range over time. ex: 333337777772221115556668888
plt.figure()
plt.plot(gazedata['time'],gazedata['roi'], linestyle='solid',color='blue')
plt.show()
Whenever the number occurs a line is plotted. I would like to connect the lines. How can I do this? In the picture I added what I need in red.

TramineR legend position and axis

I'm working with TraMineR and I don't know how to arrange my plot. So basically what i would like to have the legend under the plot and to remove the space between the x and y axis. Any help is welcomed.
The plot:
Sample code:
seqdplot(Activities.seq, with.legend=FALSE)
legend("bottom", legend=attr(Activities.seq, "labels"),
fill=attr(Activities.seq, "cpal"),
inset=-.1, bty="o", xpd=NA, cex=.75,ncol=3)
The family of seqplot functions offers a series of arguments to control the legend as well as the axes. Look at the help page of seqplot (and of plot.stslist.statd for specific seqdplot parameters).
For instance, you can suppress the x-axis with axes=FALSE, and the y-axis with yaxis=FALSE.
To print the legend you can let seqdplot display it automatically using the default with.legend=TRUE option and control it with for examples cex.legend for the font size, ltext for the text. You can also use the ncol argument to set the number of columns in the legend.
The seqplot functions use by default layout to organize the graphic area between the plots and the legend. If you need more fine tuning (e.g. to change the default par(mar=c(5.1,4.1,4.1,2.1)) margins around the plot and the legend), you should create separately the plot(s) and the legend and then organize them yourself using e.g. layout or par(mfrow=...). In that case, the separate graphics should be created by setting with.legend=FALSE, which prevents the display of the legend and disables the automatic use of layout.
The color legend is easiest obtained with seqlegend.
I illustrate with the mvad data that ships with TraMineR. First the default plot with the legend. Note the use of border=NA to suppress the too many vertical black lines.
library(TraMineR)
data(mvad)
mvad.scode <- c("EM", "FE", "HE", "JL", "SC", "TR")
mvad.seq <- seqdef(mvad, 17:86,
states = mvad.scode,
xtstep = 6)
# Default plot with the legend,
seqdplot(mvad.seq, border=NA)
Now, we suppress the x and y axes and modify the display of the legend
seqdplot(mvad.seq, border=NA,
axes=FALSE, yaxis=FALSE, ylab="",
cex.legend=1.3, ncol=6, legend.prop=.11)
Here is how you can control the space between the plot and the x and y axes
seqdplot(mvad.seq, border=NA, yaxis=FALSE, xaxis=FALSE, with.legend=FALSE)
axis(2, line=-1)
axis(1, line=0)
Creating the legend separately and reducing the left, top, and right margins around the legend
op <- par(mar=c(5.1,0.1,0.1,0.1))
seqlegend(mvad.seq, ncol=2, cex=2)
par(op)

Looping across files to overlay contours from different datasets onto one pcolor map

I am trying to have a pcolor plot from one dataset on a polar stereographic grid, and then overlay many contours for one level , but these contours are being defined from a 3d dataset of their own. I am getting the error:
RuntimeError: Can not put single artist in more than one figure
# load lat lons
fid = Dataset(ifile_for_lat_lon)
lon=fid.variables['TLON'][:]
lat=fid.variables['TLAT'][:]
fid.close()
def get_basemap():
fig = plt.figure('Background')
fig.add_subplot(111)
m = Basemap(projection='npstere',boundinglat=65,lon_0=270,resolution='l')
x,y = m(lon,lat) # compute map proj coordinates
m.pcolor(x,y,raster_data,vmin=0,vmax=1,cmap='Blues_r')
m.colorbar(location='right')
m.drawcoastlines()
m.fillcontinents(color='grey',lake_color='navy')
# draw parallels and meridians.
m.drawparallels(np.arange(-80.,81.,20.))
m.drawmeridians(np.arange(-180.,181.,20.))
m.drawmapboundary(fill_color='navy')
plt.legend(loc='lower right')
return m,x,y
# run get_basemap once to get background map
m,x,y = get_basemap()
for year in np.arange(1979,2017):
year=str(year)
# contour levels
clevs=np.array([0.7])
# load data
nc_fid = Dataset(ifile,'r')
data = nc_fid.variables['data'][0,:,:]
nc_fid.close()
cnplot = m.contour(x,y,data,clevs,cmap=plt.cm.jet,linewidth=20)
#for member in cnplot.collections:
# member.remove()
plt.show()
The first plot of the loop works fine -- the background raster with associated contour is displayed.
As soon as the loop goes through the second iteration, it complains there
RuntimeError: Can not put single artist in more than one figure
I just want the loop so I can read the new rasters so it knows where to put the overlaying contours. So, in the end, I need a background raster with a lot of contours on top (but those rasters will not be displayed, just the contour level information from them on top of the original background from the first file)

colorbars for grid of line (not contour) plots in matplotlib

I'm having trouble giving colorbars to a grid of line plots in Matplotlib.
I have a grid of plots, which each shows 64 lines. The lines depict the penalty value vs time when optimizing the same system under 64 different values of a certain hyperparameter h.
Since there are so many lines, instead of using a standard legend, I'd like to use a colorbar, and color the lines by the value of h. In other words, I'd like something that looks like this:
The above was done by adding a new axis to hold the colorbar, by calling figure.add_axes([0.95, 0.2, 0.02, 0.6]), passing in the axis position explicitly as parameters to that method. The colorbar was then created as in the example code here, by instantiating a ColorbarBase(). That's fine for single plots, but I'd like to make a grid of plots like the one above.
To do this, I tried doubling the number of subplots, and using every other subplot axis for the colorbar. Unfortunately, this led to the colorbars having the same size/shape as the plots:
Is there a way to shrink just the colorbar subplots in a grid of subplots like the 1x2 grid above?
Ideally, it'd be great if the colorbar just shared the same axis as the line plot it describes. I saw that the colorbar.colorbar() function has an ax parameter:
ax
parent axes object from which space for a new colorbar axes will be stolen.
That sounds great, except that colorbar.colorbar() requires you to pass in a imshow image, or a ContourSet, but my plot is neither an image nor a contour plot. Can I achieve the same (axis-sharing) effect using ColorbarBase?
It turns out you can have different-shaped subplots, so long as all the plots in a given row have the same height, and all the plots in a given column have the same width.
You can do this using gridspec.GridSpec, as described in this answer.
So I set the columns with line plots to be 20x wider than the columns with color bars. The code looks like:
grid_spec = gridspec.GridSpec(num_rows,
num_columns * 2,
width_ratios=[20, 1] * num_columns)
colormap_type = cm.cool
for (x_vec_list,
y_vec_list,
color_hyperparam_vec,
plot_index) in izip(x_vec_lists,
y_vec_lists,
color_hyperparam_vecs,
range(len(x_vecs))):
line_axis = plt.subplot(grid_spec[grid_index * 2])
colorbar_axis = plt.subplot(grid_spec[grid_index * 2 + 1])
colormap_normalizer = mpl.colors.Normalize(vmin=color_hyperparam_vec.min(),
vmax=color_hyperparam_vec.max())
scalar_to_color_map = mpl.cm.ScalarMappable(norm=colormap_normalizer,
cmap=colormap_type)
colorbar.ColorbarBase(colorbar_axis,
cmap=colormap_type,
norm=colormap_normalizer)
for (line_index,
x_vec,
y_vec) in zip(range(len(x_vec_list)),
x_vec_list,
y_vec_list):
hyperparam = color_hyperparam_vec[line_index]
line_color = scalar_to_color_map.to_rgba(hyperparam)
line_axis.plot(x_vec, y_vec, color=line_color, alpha=0.5)
For num_rows=1 and num_columns=1, this looks like:

How to create a scatter plot legend with only one symbol for each label?

How can I create a scatter plot legend without two symbols showing up each time? I can understand why you'd want this when you're joining symbols by lines, but for a pure scatter plot, all I want in the legend is one example of the symbol. This plot from a previous stackoverflow post shows the kind of thing I mean:
In the legend command you can use the scatterpoints option:
ax.legend(loc=0, scatterpoints = 1)
For a normal plot, it is the option numpoints.
Here you can find more information about the keyword arguments for the legend: http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.legend