I've got a problem with python...
I want a to plot a bunch of points; in addition I want to vary the color of the points continuously. For example:
x = range(10)
y = range(10)
plot(x,y,'.')
The first dot dark blue, the second one a bit paler and so on...
As a first step I tried to pass a differing grey scale to the function, but raised the error 'could not convert string to float'... What kind of variable is passed? How can I avoid the error?
for i in range(10):
plot(x,y,'i*0,1')
Thank you in advance for helping me out. I haven't found anything on the web but I think this would be quite handy for a lot of people...
Try using scatter rather than plot:
x = range(10)
y = range(10)
plt.scatter(x,y,s=60,c=x,cmap=plt.get_cmap('seismic'))
The c keyword argument specifies what values should be mapped to color. I just used the x-values here, but you could use any array of the same length. The cmap keyword argument specifies how to map the values to colors. You can see some other colormaps here: http://matplotlib.org/examples/color/colormaps_reference.html
You can use a different colormap as well:
plt.scatter(x,y,s=60,c=x,cmap=plt.get_cmap('spectrum'))
Related
I am trying to make the scatter dots have the same color if they have the same (x,y) values but with a different Z value.
so far I managed to use one variable either x or y, but I cant "zip" them together somehow.
df["X"]=pd.Categorical(df["X"])
df["Y"]=pd.Categorical(df["Y"])
df["X"].cat.codes
df["Y"].cat.codes
bx.scatter(xs,ys,zs, zdir=zs, c=df["X"].cat.codes,cmap="Set1", alpha=1)
I tried to zip them individually, I tried making an array out of them...If I try with
df["cat"]=pd.Categorical(zip(df["X"],df["Y"]))
df["cat"].cat.codes
all I get is one category code, so everything is the same.
Any ideas?
image for clarification
At first I thought the dates should be the category, but that doesnt makes sense because every day ( since the Zaxes is in datetime format) would have a different a color.
Insstead, every possible (x,y) pair ie. (1,-1), (2,1) etc should be a category(is it the right word to use?) by itself so then every pair should have its own color for example (1,-1) is black, (2,1) is red independently of its Z coordinate.
the solution was quite easy in fact, it just took some tinkering round
Original DF has X,Y,Date columns.
xs=df.X
ys=df.Y
zs=np.array(df_dates2num)
N=len(df)
val_x=df["X"].tolist()
val_y=df["Y"].tolist()
df["pairs"]=pd.Series(list(zip(val_x,val_y)), index=df.index) #make(x,y) pairs
df["pairs"]=df["pairs"].astype("category")
df["pairs"]=df.pairs.cat.codes
bx.scatter(xs,ys,zs, zdir=zs, c=df["pairs"], alpha=1, s=50) #scatter dots
and it actually works, the only thing missing is to use a more discrete color palette.
I would like to create a visualization like the upper part of this image. Essentially, a heatmap where each point in time has a fixed number of components but these components are anchored to the y axis by means of labels (that I can supply) rather than by their first index in the heatmap's matrix.
I am aware of pcolormesh, but that does not seem to give me the y-axis functionality I seek.
Lastly, I am also open to solutions in R, although a Python option would be much preferable.
I am not completely sure if I understand your meaning correctly, but by looking at the picture you have linked, you might be best off with a roll-your-own solution.
First, you need to create an array with the heatmap values so that you have on row for each label and one column for each time slot. You fill the array with nans and then write whatever heatmap values you have to the correct positions.
Then you need to trick imshow a bit to scale and show the image in the correct way.
For example:
# create some masked data
a=cumsum(random.random((20,200)), axis=0)
X,Y=meshgrid(arange(a.shape[1]),arange(a.shape[0]))
a[Y<15*sin(X/50.)]=nan
a[Y>10+15*sin(X/50.)]=nan
# draw the image along with some curves
imshow(a,interpolation='nearest',origin='lower',extent=[-2,2,0,3])
xd = linspace(-2, 2, 200)
yd = 1 + .1 * cumsum(random.random(200)-.5)
plot(xd, yd,'w',linewidth=3)
plot(xd, yd,'k',linewidth=1)
axis('normal')
Gives:
Create a method plot(window, expression, color = "black") to plot the expression in the
window.
This is what i've done:
from math import *
from graphics import *
win = GraphWin()
def plot(window, expression, color = "black"):
#Evaluates given expression and plots it in "window". Returns the list of all the plotted points.
points = []
#Evalute expression over 1000 different values and for each (x,y) pair plot the point.
for i in range(0, 1001):
try:
x = i/100.0
y = eval(expression)
plot(x,y)
except Exception:
print("For ", x, " the expression is invalid")
return points
So i guess i have done something wrong. Can someone help me? :)
Looking at your code you have a function called plot that calls plot - this is because of the classic error of from somewhere import *.
I suspect that you are trying to call graphics.plot within plot so get rid of the from graphics import * and put graphics. before the items that you are using from there.
You are also not filling in, or using your points list.
There are a couple of obvious problems:
You create a list of points, never put anything into it, then return it (still empty) at the end; and
For each individual point x, y you call plot again recursively (see Steve Barnes' answer), passing x as window and y as expression.
I suggest you separate this into two parts: one to create a list of points based on the function, and one to plot this list of points.
don't use the name plot as your own function name, this will shadow the matplotlib.pyplot.plot method name if you have import *.
the matplotlib plot method is used to create lines, which needs a series of Xs and Ys each time you call it. E.g., plot(1,2) or plot([1], [2]) will plot nothing in the figure, while plot([1,2], [3,4]) draws a line between point (1,3) and (2,4). You need to call scatter(1, 2) if you insist on plotting one point each time.
Let's say I have two histograms and I set the opacity using the parameter of hist: 'alpha=0.5'
I have plotted two histograms yet I get three colors! I understand this makes sense from an opacity point of view.
But! It makes is very confusing to show someone a graph of two things with three colors. Can I just somehow set the smallest bar for each bin to be in front with no opacity?
Example graph
The usual way this issue is handled is to have the plots with some small separation. This is done by default when plt.hist is given multiple sets of data:
import pylab as plt
x = 200 + 25*plt.randn(1000)
y = 150 + 25*plt.randn(1000)
n, bins, patches = plt.hist([x, y])
You instead which to stack them (this could be done above using the argument histtype='barstacked') but notice that the ordering is incorrect.
This can be fixed by individually checking each pair of points to see which is larger and then using zorder to set which one comes first. For simplicity I am using the output of the code above (e.g n is two stacked arrays of the number of points in each bin for x and y):
n_x = n[0]
n_y = n[1]
for i in range(len(n[0])):
if n_x[i] > n_y[i]:
zorder=1
else:
zorder=0
plt.bar(bins[:-1][i], n_x[i], width=10)
plt.bar(bins[:-1][i], n_y[i], width=10, color="g", zorder=zorder)
Here is the resulting image:
By changing the ordering like this the image looks very weird indeed, this is probably why it is not implemented and needs a hack to do it. I would stick with the small separation method, anyone used to these plots assumes they take the same x-value.
It is a simple but common task required when trying to fix a colormap according to a 2D matrix of values.
To demonstrate consider the problem in Matlab, the solution does not need to be in Matlab (i.e., the code presented here is only for demonstration purpose).
x = [0,1,2; 3,4,5; 6,7,8];
imagesc(x)
axis square
axis off
So the output is as:
when some values change to over the maximum value it happens like:
x = [0,1,2; 3,4,5; 6,7,18];
which looks logical but makes problems when we wish to compare/trace elements in two maps. Since the colormap association is changed it is almost impossible to find an individual cell for comparison/trace etc.
The solution I implemented is to mask the matrix as:
x = [0,1,2; 3,4,5; 6,7,18];
m = 8;
x(x>=m) = m;
which works perfectly.
Since the provided code requires searching/filtering (extra time consuming!) I wonder if there is a general/more efficient way for this job to be implemented in Matlab, Python etc?
One of the cases that this issue occurs is when we have many simulations sequentially and wish to make a sense-making animation of the progress; in this case each color should keep its association fixed.
In Python using package MatPlotLib the solution is as follows:
import pylab as pl
x = [[0,1,2],[3,4,5],[6,7,18]]
pl.matshow(x, vmin=0, vmax=8)
pl.axis('image')
pl.axis('off')
show()
So vmin and vmax are boundary limits for the full range of colormap.
The indexing is pretty quick so I don't think you need worry.
However, in Matlab, you can pass in the clims argument to imagesc:
imagesc(x,[0 8]);
This maps all values above 8 to the top colour in the colour scale, and all values below 0 to the bottom colour in the colour scale, and then stretches the scale for colours in-between.
imagesc documentation.
f1 = figure;
x = [0,1,2; 3,4,5; 6,7,8];
imagesc(x)
axis square
axis off
limits = get(gca(f1),'CLim');
f2 = figure;
z = [0,1,2; 3,4,5; 6,7,18];
imagesc(z)
axis square
axis off
caxis(limits)