Setting scatter points transparency from data array in matplotlib plot - python

I am plotting data with matplotlib, I have obtained a scatter plot from two numpy arrays:
ax1.scatter(p_100,tgw_e100,color='m',s=10,label="time 0")
I would like to add information about the eccentricity of each point.
For this purpose I have a third array of the same length of p_100 and tgw_e100, ecc_100 whose items range from 0 to 1.
So I would like to set the transparency of my points using data from ecc_100 creating some sort of shade scale.
I have tried this:
ax1.scatter(p_100,tgw_e100,color='m',alpha = ecc_100,s=10,label="time 0")
But I got this error:
ValueError: setting an array element with a sequence.

According to the documentation alpha can only be a scalar value.
Thus I can't see any other way than looping over all your point one by one.
for x, y, a in zip(p_100, tgw_e100, ecc_100):
ax1.scatter(x, y, color='m',alpha = a, s=10)
I think the labelling will be quite weird though, so you might have to create the legend by hand.
I omitted that from my solution.
I guess a patch to make the alpha keyword argument behave like c and s would be welcome.
Update May 6 2015
According to this issue, changing alpha to accept an array is not going to happen. The bug report suggests to set the colors via an RGBA array to control the alpha value. Which sounds better than my suggestion to plot each point by itself.
c = np.asarray([(0, 0, 1, a) for a in alpha])
scatter(x, y, color=c, edgecolors=c)

Another option is to use a the cmap argument to provide a colormap, and the c argument to provide mappings of how dark/light you want the colors. Check out this question: matplotlib colorbar for scatter
Here's all the matplotlib colormaps: http://matplotlib.org/examples/color/colormaps_reference.html I suggest a sequential colormap like PuRd. If the colors are getting darker in the opposite direction, you can use the "reversed" colormap by appending _r to the name, like PuRd_r.
Try this out:
ax1.scatter(p_100, tgw_e100, c=ecc_100, cmap='PuRd', s=10, label='time 0')
Hope that helps!

Here is a scatter plot of three columns using transparency.
x = sample_df['feature_1']
y = sample_df['feature_2']
#e = {'label_x': 'b', 'label_y': 'r'}
# label_x will be in red, label_y will be in blue
e = {'label_x': np.asarray((1, 0, 0, .1)), 'label_y': np.asarray((0, 0, 1, .1))}
colr = sample_df['label_bc'].map(e)
plt.scatter(x, y, c=colr);

Related

Changing colors in a scatterplot using Matplotlib with python

I am currently taking a Matplotlib class. I was given an image to create the image as a 3D subplot 4 times at 4 different angles. It's a linear plot. As the data changes the plots change colors. As it's an image, I'm not certain where the actual changes start. I don't want an exact answer, just an explanation of how this would work. I have found many methods for doing this for a small list but this has 75 data points and I can't seem to do it without adding 75 entries.
I've also tried to understand cmap but I am confused on it as well.
Also, it needs to done without Seaborn.
This is part of the photo.
I am finding your question a little bit hard to understand. What I think you need is a function to map the input x/y argument onto a colour in your chosen colour map. See the below example:
import numpy as np
import matplotlib.pyplot
def number_to_colour(number, total_number):
return plt.cm.rainbow(np.linspace(0,1.,total_number))[list(number)]
x = np.arange(12)
y = x*-3.
z = x
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c=number_to_colour(x, len(x)))
plt.show()
plt.cm.rainbow(np.linspace(0,1.,total_number)) creates an array of colours of length total_number evenly spaced spaced across the colour map (in this case rainbow). Modifying the indexing of this array (or changing np.linspace to another function with the desired scaling), should give you the colour scaling that you need.

How can I normalize colormap in matplotlib scatter plot?

The matplotlib documentation explain in detail how to normalize colormaps for a pcolormesh, but how can I correctly do it for a scatter plot?
normalize = mcolors.Normalize(vmin=-1, vmax=1)
plt.scatter(x,y,z,cmap=colormap(normalize),marker='*',s=5)
doesn't work (TypeError: Cannot cast array data from dtype('O') to dtype('int64') according to the rule 'safe')
it's just that the z data are not exactly from -1 to 1, I am plotting multiple datasets that have the limits around +/- 0.93 - 98, but I want the colours to be centered at zero and go from -1 to 1 so that I have the same reference for all the various datasets.
Oh, and when I don't attempt to normalize, I get TypeError: scatter() got multiple values for keyword argument 's'. Clearly I don't know how to use colormap in scatter plots.
The syntax you're using is completely different to the one in the linked documentation. There is essentially no difference between normalizing a scatter or a pcolor(mesh) or just any other scalar mappable object.
It's always
colormap = plt.cm.bwr #or any other colormap
normalize = matplotlib.colors.Normalize(vmin=-1, vmax=1)
plt.scatter(x, y, c=z, s=5, cmap=colormap, norm=normalize, marker='*')
# define the range of values in the data (100 is arbitrary)
my_range = np.linspace(-1,1,100)
# cmap is a function. It returns (rgba) colors base on a range 0-1. Therefore,
# transform your values to 0-1 to use them as input for cmap()
cmap = cm.get_cmap('viridis', 100)
my_transformed_range = (my_range - np.min(my_range)) / (np.max(my_range) - np.min(my_range))
# colors should be supplied as a single color or a list (here using the cmap fx)
plt.scatter(my_range, np.ones(100), color=[cmap(i) for i in my_transformed_range])

Use a variable to set alpha opacity in a colormap

I would like to plot the 2 output variables, say map1 and map2, as a function of 2 input variables, say x and y using colormaps. So as to do so, I want to represent map1 using a color scale while map2 would rely on a transparency scale. Yet, the alpha option cannot take an np.array as an argument and the following code is doomed to failure.
fig=plt.figure(num=None, figsize=(21,12), dpi=80, facecolor='w', edgecolor='k')
ax1=plt.subplot(211)
im = ax1.pcolor(map1, cmap='Spectral_r', alpha=map2)
fig.colorbar(im)
Would anybody see a way to do this? I don't want to use another overlapped color scale and really want map2 to be represented with a transparency function so as the visibility of a background grid for instance would tell the reader the amplitude of map2.
You could do this with pcolormesh, and set the alpha for the faces of the QuadMesh afterwards. For example:
import numpy as np
import matplotlib.pyplot as plt
fig,ax = plt.subplots(1)
ax.set_aspect('equal')
# The data array
m1 = np.random.rand(5,5)
# The alpha array. Normalize your map2 to the range 0,1
m2 = np.linspace(0,1,25).reshape(5,5)
p = ax.pcolormesh(m1)
plt.savefig('myfig.png') # or fig.canvas.draw()
for i,j in zip(p.get_facecolors(),m2.flatten()):
i[3] = j # Set the alpha value of the RGBA tuple using m2
plt.savefig('myfig.png')
Note: you seem to have to save the figure (or plt.show() or fig.canvas.draw()) after the pcolormesh command, to generate the p.get_facecolors array; that's why I save the figure twice. There is probably a more elegant solution to that, but I can't think of it off the top of my head. Here's the output; notice the alpha increase from the bottom left towards the top right:

Fast way to convert an array of integers to color strings or color values in python

I am trying to plot data points according to their class labels.
import numpy
import matplotlib as plt
x = numpy.random.uniform(size = [1, 15])
labels = numpy.array([1,2,2,2,2,1,1,2,3,1,3,3,1,1, 3])
plt.plot(x, 'o', c = labels)
When I did the above, Python complained that the color values need to be 0, 1. Then I used
plt.plot(x, 'o', c = labels/max(labels))
There is no error generated. A plot window pops up, but there is nothing in the plot window. I am wondering what is the correct way to define the colors that are according to the data labels?
I am also trying to color nodes according to the class labels. This is done in networkx. A simple example is:
import networkx as nx
G=nx.complete_graph(5)
nx.draw(G, node_col = node_labels)
The array node_labels will be the labels of the 5 vertices. I tried using the same approaches I tried above, but the network always has red nodes.
Any insight will be appreciated. Thanks!
Since your labels are integers you can use them as an index for a list of colors:
colors = ['#e41a1c', '#377eb8', '#4daf4a']
then, using scatter is simpler than plot since you can provide a list/sequence of colors:
labels = np.random.randint(low=0, high=3, size=20)
plt.scatter(np.random.rand(20), np.random.rand(20), color=np.array(colors)[labels])
Which will give you this:
To get nice colors you can use colorbrewer.
In order to do what you're seeking, your labels array must be a floating-point array. From the look of it, [labels] is being interpreted as a integer array. Thus, modify your code as follows to achieve the desired result.
plt.plot(x, 'o', c = labels)
should be changed to:
plt.plot(x, 'o', c = labels.astype(numpy.float)
Stay awesome!!

Change axes ticks of quiver - Python

I'm plotting a vector field with the quiver method of Matplotlib.
My array to store this vector has a dimension x * y but I'm working with a space that varies from -2 to 2.
So far, to plot the vector field I have this method:
import matplotlib.pyplot as plt
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
plt.subplots()
plt.quiver(vector_field_x, vector_field_y)
plt.savefig(file_path + '.png')
plt.close()
Which gives me this output, as an example, for a 10 x 10 array:
But to generate this vector field I centered my data in the x = 0, y = 0, x and y ranging from -2 to 2.
Then, I would like to plot the axis of the image following this pattern.
As an standard approach, I tried to do the following:
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
fig, ax = plt.subplots()
ax.quiver(vector_field_x, vector_field_y)
ax.set_xticks([-2, 0, 2])
ax.set_yticks([-2, 0, 2])
plt.savefig(file_path + '.png')
plt.close()
Which usually works with Matplotlib methods, as imshow and streamplot, for example.
But this what I've got with this code:
Which is not what I want.
So, I'm wondering how can I perform what I explained here to change the axes ticks.
Thank you in advance.
Funny thing, I just learnt about quiver yesterday... :)
According to the quiver documentation, the function can accept from 2 to 5 arguments...
The simplest way to use the function is to pass it two arrays with equal number of elements U and V. Then, matplotlib will plot an arrow for each element in the arrays. Specifically, for each element i,j you will get an arrow placed at i,j and with components defined by U[i,j] and V[i,j]. This is what is happening to you
A more complete syntax is to pass our arrays with equal number of elements X, Y, U and V. Again, you will get an arrow for each i,j element with components defined by U[i,j] and V[i,j], but this time they will be placed at coordinates X[i,j], Y[i,j].
In conclusion:
you need to call quiver like
quiver(values_x, values_y, vector_field_x, vector_field_y)
Probably you already did it, but you can get values_x and values_y using the numpy.meshgrid function.
The matplotlib example for the quiver function might be useful, also.
I hope it helps!

Categories