MatplotLib: Scatter of Unicode characters with URL links - matplotlib

I want to export a matplotlib scatter plot as a SVG with a different hyperlink from each scatter points which are not simple markers but Unicode characters.
I've try the following:
import matplotlib.cm as cm
import matplotlib as mpl
import matplotlib.pyplot as pyplot
mpl.rcParams['text.usetex'] = True
mpl.rcParams['text.latex.preamble'] = [r'\usepackage{amsmath}'] #for \text command
f = pyplot.figure()
stemp='6F22'
markerstring=r'$\\unichar{"%s}$' % stemp
print(markerstring)
ss = pyplot.scatter([1, 2, 3], [4, 5, 6],color='black',s=[100, 0, 0],alpha=0.5, marker=markerstring)
ss.set_urls(['http://www.bbc.co.uk/news', 'http://www.google.com', None])
f.savefig('scatter.svg')
It either crashs because "\u" or "\unichar" is unknown
Or displays 6F22 instead of 漢 in the final SVG

Related

Matplotlib adjust inset_axes based on loc parameter instead of bbox?

I'm using inset_axes() to control the placement of my colorbar legend. The label hangs off the plot just a little bit. Is there a way to just nudge it over without having to do bbox_to_anchor()? Some way to do an offset from the loc parameter? I do want to keep it in the lower left.
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
set1 = ax2.scatter(df.x, df.y,
edgecolors = 'none',
c = df.recommended_net_preferred_for_analysis_meters,
norm = mcolors.LogNorm(), cmap='jet')
cbaxes = inset_axes(ax2, width="30%", height="3%", loc=3)
plt.colorbar(set1, cax=cbaxes, format = '%1.2f', orientation='horizontal')
cbaxes.xaxis.set_ticks_position("top")

plotting a svg or pdf into matplotlib

I have the same file saved both as .pdf and as .svg
I'd like to insert the file in a regular matplotlib plot.
How can I do that?
import matplotlib.pyplot as plt
pdfFile = open('file.pdf')
svgFile = open('file.svg')
fig,ax = plt.subplots(1,2)
ax[0].imshow(pdfFile)
ax[1].imshoe(svgFile)
plt.show()
Alternately I've tried with
from svglib.svglib
import svg2rlg
from reportlab.graphics import renderPDF, renderPM >>> >>> drawing = svg2rlg("file.svg") >>> renderPDF.drawToFile(drawing, "file.pdf")

how to customize color legend when using for loop in matplotlib, scatter

I want to draw a 3D scatter, in which the data is colored by group. Here is the data sample:
aa=pd.DataFrame({'a':[1,2,3,4,5],
'b':[2,3,4,5,6],
'c':[1,3,4,6,9],
'd':[0,0,1,2,3],
'e':['abc','sdf','ert','hgf','nhkm']})
Here, a, b, c are axis x, y, z. e is the text shown in the scatter. I need d to group the data and show different colors.
Here is my code:
fig = plt.figure()
ax = fig.gca(projection='3d')
zdirs = aa.loc[:,'e'].__array__()
xs = aa.loc[:,'a'].__array__()
ys = aa.loc[:,'b'].__array__()
zs = aa.loc[:,'c'].__array__()
colors = aa.loc[:,'d'].__array__()
colors1=np.where(colors==0,'grey',
np.where(colors==1,'yellow',
np.where(colors==2,'green',
np.where(colors==3,'pink','red'))))
for i in range(len(zdirs)): #plot each point + it's index as text above
ax.scatter(xs[i],ys[i],zs[i],color=colors1[i])
ax.text(xs[i],ys[i],zs[i], '%s' % (str(zdirs[i])), size=10, zorder=1, color='k')
ax.set_xlabel('a')
ax.set_ylabel('b')
ax.set_zlabel('c')
plt.show()
But I do not know how to put a legend on the plot. I hope my legend is like:
The colors and the numbers should match and be ordered.
Could anyone help me with how to customize the color bar?
First of all, I've taken the liberty to reduce your code a bit:
I'd suggest to create a ListedColormap to map integer->color, which allows you to pass the color column via c=aa['d'] (note it's c=, not color=!)
you don't need to use __array__() here, in the code below you can directly use aa['a']
finally, you can add an empty scatter plot for each color in the ListedColormap, and this can then be rendered correctly by ax.legend()
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib.colors import ListedColormap
import matplotlib.patches as mpatches
aa=pd.DataFrame({'a':[1,2,3,4,5],
'b':[2,3,4,5,6],
'c':[1,3,4,6,9],
'd':[0,0,1,2,3],
'e':['abc','sdf','ert','hgf','nhkm']})
fig = plt.figure()
ax = fig.gca(projection='3d')
cmap = ListedColormap(['grey', 'yellow', 'green', 'pink','red'])
ax.scatter(aa['a'],aa['b'],aa['c'],c=aa['d'],cmap=cmap)
for x,y,z,label in zip(aa['a'],aa['b'],aa['c'],aa['e']):
ax.text(x,y,z,label,size=10,zorder=1)
# Create a legend through an *empty* scatter plot
[ax.scatter([], [], c=cmap(i), label=str(i)) for i in range(len(aa))]
ax.legend()
ax.set_xlabel('a')
ax.set_ylabel('b')
ax.set_zlabel('c')
plt.show()

How can I set boxplot color by rainbow in matplotlib

I want to create boxplot of data in comparing, my plot looks like
how can I add color like
You can color the box following this example. Beyond that, you will need to map your data in mind to color on the "rainbow" colormap with this module. Here is an example with random test data. I map colors with means in this example.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
# Random test data
test_data = [np.random.normal(mean, 1, 100) for mean in range(50)]
fig, axes = plt.subplots(figsize=(12, 16))
# Horizontal box plot
bplot = axes.boxplot(test_data,
vert=False, # vertical box aligmnent
patch_artist=True) # fill with color
# Fill with colors
cmap = cm.ScalarMappable(cmap='rainbow')
test_mean = [np.mean(x) for x in test_data]
for patch, color in zip(bplot['boxes'], cmap.to_rgba(test_mean)):
patch.set_facecolor(color)
plt.show()
You can use the cmap property to actually be a function, accepting values between 0 and 1, and call it "normalising" your data. Using matplotlib example on boxplots:
import matplotlib.pyplot as plt
import numpy as np
# Random test data
np.random.seed(123)
all_data = [np.random.normal(0, 5, 100) for std in range(1, 21)]
fig, ax = plt.subplots(nrows=1, figsize=(9, 4))
# rectangular box plot
bplot = ax.boxplot(all_data, 0, '', 0, patch_artist=True)
cm = plt.cm.get_cmap('rainbow')
colors = [cm(val/len(all_data)) for val in range(len(all_data))]
for patch, color in zip(bplot['boxes'], colors):
patch.set_facecolor(color)
plt.show()

Matplotlib: add_lines to colorbar with defined properties (color: OK; dotted: not OK)

I want to place a line at one level (e.g., 0) in the colorbar of a contourf plot with matplotlib.
With the following code, I can do it but not all the properties of the contour lines are conserved (i.e., the color and width of the line are correct, but I can't have it dotted in the colorbar).
Any idea of how to have a dotted line corresponding to a desired level in the colorbar?
import matplotlib.pyplot as plt
import numpy
x=y=range(10)
z=numpy.random.normal(0,2,size=(10,10))
surfplot=plt.contourf(x,y,z, cmap=plt.cm.binary_r)
cont=plt.contour(surfplot, levels=[0], colors='r', linewidths=5, linestyles=':')
cbar=plt.colorbar(surfplot)
cbar.add_lines(cont)
plt.show()
You could plot a horizontal line on your color bar directly.
cax = cbar.ax
cax.hlines(0.5, 0, 1, colors = 'r', linewidth = 10, linestyles = ':')
You'll have to calculate the y-coordinate of the line based on the data and the coloramp.
Colorbar.add_lines() currently only retains the colors and line widths.
However, you can update the line style of the new LineCollection after adding it:
import matplotlib.pyplot as plt
import numpy
plt.style.use('classic') # to match the look in the question
x = y = range(10)
z = numpy.random.normal(0, 2, size=(10, 10))
surfplot = plt.contourf(x, y, z, cmap=plt.cm.binary_r)
cont = plt.contour(surfplot, levels=[0], colors='r', linewidths=5, linestyles=':')
cbar = plt.colorbar(surfplot)
cbar.add_lines(cont)
cbar.lines[-1].set_linestyles(cont.linestyles) # adopt the contour's line styles
plt.show()