I am trying to plot a series of curves on the same graph with individual markers:
Each curve has one colour
Each data point has its own markers
For this, I created 3 lists of lists: x_data, y_data and markers. Using np.array(), x_data and y_data can be plotted properly as different curves (with individual colours).
However, np.array() cannot be used with the attribute marker and I do not know how to pass markers to ax.plot().
Does someone know how to attribute individual markers?
MWE
import matplotlib.pyplot as plt
import numpy as np
x_data=[[1,2,3,4,5],[5,10,3,8,6]]
y_data=[[5,10,3,8,6],[1,2,3,4,5]]
markers=[["o","+","D","+","D"],["D","o","o","D","+"]]
fig, ax = plt.subplots()
for n in range(0,len(x_data)):
ax.plot(np.array(x_data[n]), np.array(y_data[n]),linewidth=1,marker=np.array(markers))
plt.show()
One option is an inner loop to scatter plot each marker individually:
import matplotlib.pyplot as plt
import numpy as np
x_data=[[1,2,3,4,5],[5,10,3,8,6]]
y_data=[[5,10,3,8,6],[1,2,3,4,5]]
markers=[["o","+","D","+","D"],["D","o","o","D","+"]]
fig, ax = plt.subplots()
for xs, ys, markers in zip(x_data, y_data, markers):
line = ax.plot(xs, ys, linewidth=1)
colour = line[0].get_color()
for x, y, marker in zip(xs, ys, markers):
ax.scatter(x, y, marker=marker, color=colour)
plt.show()
Output:
Related
I'm working with data that has the data has 3 plotting parameters: x,y,c. How do you create a custom color value for a scatter plot?
Extending this example I'm trying to do:
import matplotlib
import matplotlib.pyplot as plt
cm = matplotlib.cm.get_cmap('RdYlBu')
colors=[cm(1.*i/20) for i in range(20)]
xy = range(20)
plt.subplot(111)
colorlist=[colors[x/2] for x in xy] #actually some other non-linear relationship
plt.scatter(xy, xy, c=colorlist, s=35, vmin=0, vmax=20)
plt.colorbar()
plt.show()
but the result is TypeError: You must first set_array for mappable
From the matplotlib docs on scatter 1:
cmap is only used if c is an array of floats
So colorlist needs to be a list of floats rather than a list of tuples as you have it now.
plt.colorbar() wants a mappable object, like the CircleCollection that plt.scatter() returns.
vmin and vmax can then control the limits of your colorbar. Things outside vmin/vmax get the colors of the endpoints.
How does this work for you?
import matplotlib.pyplot as plt
cm = plt.cm.get_cmap('RdYlBu')
xy = range(20)
z = xy
sc = plt.scatter(xy, xy, c=z, vmin=0, vmax=20, s=35, cmap=cm)
plt.colorbar(sc)
plt.show()
Here is the OOP way of adding a colorbar:
fig, ax = plt.subplots()
im = ax.scatter(x, y, c=c)
fig.colorbar(im, ax=ax)
If you're looking to scatter by two variables and color by the third, Altair can be a great choice.
Creating the dataset
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.DataFrame(40*np.random.randn(10, 3), columns=['A', 'B','C'])
Altair plot
from altair import *
Chart(df).mark_circle().encode(x='A',y='B', color='C').configure_cell(width=200, height=150)
Plot
I'm fairly new to scatter plots and python in general. I am trying to plot a third variable against an x and a y, however, I'm not quite sure how to about specifying that argument? So I would have X values which are ints, y values which are also ints and then on the graph itself I want the model scores to show. Is there any way to do this sort of thing?
Thank you.
You can use color to plot a third value. Here is a very minimal example :
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
x = np.random.rand(100)
y = np.random.rand(100)
z = np.random.rand(100)
plt.scatter(x,y, c=z, s=5, cmap=cm.hsv)
cbar= plt.colorbar()
plt.show()
Edit
You could also use the size of markers, their transparency, hue or rgb values to depict even more information. Here is an example with marker size, alpha level and color on a perceptually uniform colormap.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
import matplotlib.cm as cmx
x = np.random.rand(100)
y = np.random.rand(100)
z = np.random.rand(100)
t = np.random.rand(100)
w = np.random.rand(100)
fig, ax = plt.subplots(1, 1)
cmap = plt.get_cmap('plasma')
cNorm = colors.Normalize(vmin=0, vmax=max(z))
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cmap)
for i in range(100):
ax.scatter(x[i],y[i], c=scalarMap.to_rgba(z[i]), s=t[i]*100, cmap=cmx.plasma, alpha=w[i], edgecolor='none')
scalarMap.set_array([])
fig.colorbar(scalarMap,ax=ax)
for a in [0.1, 0.5, 0.9]:
ax.scatter([], [], c='k', alpha=0.5, s=a*100, label=str(a), edgecolors='none')
l1 = ax.legend(scatterpoints=1, frameon=True, loc='lower left' ,markerscale=1)
for b in [0.25, 0.5, 0.75]:
ax.scatter([], [], c='k', alpha=b, s=50, label=str(b), edgecolors='none')
ax.legend(scatterpoints=1, frameon=True, loc='lower right' ,markerscale=1)
fig.show()
At face value, that question doesn't really make sense because a conventional scatterplot has only two axes, and of course you can't plot points with three dimensions (x, y and accuracy).
However, there are alternative ways to do so.
Use colours
import numpy as np
from matplotlib import pyplot as plt
x = np.random.rand(200)
y = np.random.rand(200)
fig, ax = plt.subplots(figsize=(5, 5))
ax.scatter(x, y, c=(x + y), cmap='RdPu')
scatter takes a c argument, which can be a numeric value, as well as a cmap argument, which can be a string referencing a colormap.
The colormap object translates the numbers provided in c into points along a colour mapping, which you can think of as a gradient bar.
Use 3D axes
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(5, 5))
ax = Axes3D(fig)
ax.scatter(x, y, (x + y))
This turns your 3rd dimension, accuracy, into an ordinary spatial dimension.
Use size of the markers
Very similar to the color option in the first part, you can change the size of the scatter markers (given you have some idea about the scale of the values). So based on the first example, you can also do;
import numpy as np
from matplotlib import pyplot as plt
x = np.random.rand(200)
y = np.random.rand(200)
fig, ax = plt.subplots(figsize=(5, 5))
ax.scatter(x, y, c='k', s=5*(x + y), cmap='RdPu')
scatter takes also the s argument, that changes the size of the markers.
Suppose I have gridded data with dimensions (x,y) and values are in z.
so simply we can make scatter plot for third dimension by:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random(10)
y = np.random.random(10)
z = np.random.random(10)
plt.scatter(x, y, c = z, s=150, cmap = 'jet')
plt.show()
what i am thinking now is to remove the line color of each circular scatter plot. And also instead of circle can we make it square??
I did not find any way to do that. your help will be highly appreciated.
Pass the argument edgecolors='none' to plt.scatter. The patch boundary will not be drawn.
Pass the argument marker='s' to plt.scatter. The marker style will be square.
Then, we have,
The source code,
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random(10)
y = np.random.random(10)
z = np.random.random(10)
plt.scatter(x, y, c = z, s=150, cmap = 'jet', edgecolors='none', marker='s')
plt.show()
Refer to matplotlib.pyplot.scatter for more information.
I assume this is a simple fix. I'm trying to replace integer values in a 3d bar chart in matplotlib with string names, and the last one inexplicably won't show:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(11,8.5))
ax = fig.add_subplot(111, projection='3d')
for c, z in zip([qwer for qwer in ['r', 'g', 'b', 'y']*20][:len(sss.keys())], sss.keys()):
xs = np.array(sss[z].keys())
ys = np.array([sss[z][key] for key in sss[z]])
cs = [c] * len(xs)
ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('Second Interval')
ax.set_ylabel('First Interval')
ax.set_zlabel('Frequency')
ax.set_xticklabels(['skip down','step down','stay','step up','skip up'])
ax.set_yticklabels(['','skip down','','step down','','stay','','step up','','skip up'])
ax.set_title('Proportional Frequency of S/S/S Intervals by Previous Interval')
plt.show()
sss is a dictionary with other dictionaries as values.
Unfortunately I can't post images, but essentially the chart looks all good and all the string labels on the x and y axes work except 'skip up' along the y axis. It's right at the corner between the y and z axes and just doesn't appear.
What's up?
How can I create a 3D plot with a color gradient for the points? See the example below, which works for a 2D scatter plot.
Edit (thanks to Chris): What I'm expecting to see from the 3D plot is a color gradient of the points ranging from red to green as in the 2D scatter plot.
What I see in the 3D scatter plot are only red points.
Solution: for some reasons (related to the gradient example I copied elsewhere) I set xrange to len-1, which messes everything in the 3D plot.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Create Map
cm = plt.get_cmap("RdYlGn")
x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
#col = [cm(float(i)/(29)) for i in xrange(29)] # BAD!!!
col = [cm(float(i)/(30)) for i in xrange(30)]
# 2D Plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x, y, s=10, c=col, marker='o')
# 3D Plot
fig = plt.figure()
ax3D = fig.add_subplot(111, projection='3d')
ax3D.scatter(x, y, z, s=10, c=col, marker='o')
plt.show()
Here is an example for 3d scatter with gradient colors:
import matplotlib.cm as cmx
from mpl_toolkits.mplot3d import Axes3D
def scatter3d(x,y,z, cs, colorsMap='jet'):
cm = plt.get_cmap(colorsMap)
cNorm = matplotlib.colors.Normalize(vmin=min(cs), vmax=max(cs))
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x, y, z, c=scalarMap.to_rgba(cs))
scalarMap.set_array(cs)
fig.colorbar(scalarMap)
plt.show()
Of course, you can choose the scale to range between different values, like 0 and 1.
Following works: I can't figure out why yours doesn't. You should be able to set color as a sequence of RGBA floats, or just sequence of floats.
# Create Map
cm = plt.get_cmap("RdYlGn")
x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
col = np.arange(30)
# 2D Plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x, y, s=10, c=col, marker='o')
# 3D Plot
fig = plt.figure()
ax3D = fig.add_subplot(111, projection='3d')
p3d = ax3D.scatter(x, y, z, s=30, c=col, marker='o')
plt.show()
However, in help of scatter, I see the following, it may be related.
A :class:`matplotlib.colors.Colormap` instance or registered
name. If *None*, defaults to rc ``image.cmap``. *cmap* is
only used if *c* is an array of floats.