0

EDIT: I responded in the comments but I've tried the method in the marked post - my z data is not calculated form my x and y so I can't use a function like that.

I have xyz data that looks like the below:

NEW:the xyz data in the file i produce - I extract these as x,y,z

And am desperately trying to get a plot that has x against y with z as the colour.

y is binned data that goes from (for instance) 2.5 to 0.5 in uneven bins. So the y values are all the same for one set of x and z data. The x data is temperature and the z is density info.

So I'm expecting a plot that looks like a bunch of stacked rectangles where there is a gradient of colour for one bin of y values which spans lots of x values.

However all the codes I've tried don't like my z values and the best I can do is:

The axes look right but the colour bar goes from the bottom to the top of the y axis instead of plotting one z value for each x value at the correct y value

I got this to work with this code:

import matplotlib.cm as cm
from matplotlib.colors import LogNorm
import numpy as np
import scipy.interpolate
data=pandas.read_csv('Data.csv',delimiter=',', header=0,index_col=False)
x=data.tempbin
y=data.sizefracbin
z=data.den
x=x.values
y=y.values
z=z.values
X,Y=np.meshgrid(x,y)
Z=[]
for i in range(len(x)):
    Z.append(z)
Z=np.array(Z)
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.show()

I've tried everything I could find online such as in the post here: matplotlib 2D plot from x,y,z values

But either there is a problem reshaping my z values or it just gives me empty plots with various errors all to do (I think) with my z values.

Am I missing something? Thank you for your help!

Edit in reponse to : ImportanceOfBeingErnest

I tried this :

import matplotlib.cm as cm
from matplotlib.colors import LogNorm
import numpy as np
import scipy.interpolate
data=pandas.read_csv('Data.csv',delimiter=',', header=0,index_col=False)
data.sort_values('sizefrac')
x=data.tempbin
y=data.sizefrac
z=data.INP
x=x.values
y=y.values
z=z.values
X=x[1:].reshape(N,N)
Y=y[1:].reshape(N,N)
Z=z[1:].reshape(N,N)
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.show()

and got a very empty plot. Just showed me the axes and colourbar as in my attached image but pure white inside the axes! No error or anything... And the reshaping I need to remove a data point from each because otherwise the reshaping won't work

Acyna
  • 3
  • 5
  • 1
    Please, dont post pictures for your data/code. Use code format tags instead. The picture is likely to disappear one day or the other from your provider. For plotting it more difficult, I get that. Maybe wait for SO to rely on some jupyter-like plotting integration (maybe one day ?) – LoneWanderer Nov 26 '18 at 20:29
  • Also, please do code formatting for your python snippet, it is interpreted as a Python String, not Python source code. – LoneWanderer Nov 26 '18 at 20:33
  • Apologies if I misunderstand @Silmathoron but they calculated their z data from their x y data, mine is already defined - this seems to make a difference in my plots – Acyna Nov 26 '18 at 20:33
  • My bad, I misread your problem – Silmathoron Nov 26 '18 at 20:49
  • First thing, you need to sort your data by x and y (probably by y and x rather). Then, don't use meshgrid, because you already have the grid defined. Instead reshape the values such as to get 2D arrays. Then plot them. Note that it seems that your grid is defined through the centers of the pixels, not the edges, as would be assumed by pcolormesh. You will hence loose the last row and column of data. Or use `imshow`. – ImportanceOfBeingErnest Nov 26 '18 at 20:55
  • Forgot to say. Ignore the linked question, it's not very helpful here where you already have a grid defined. Maybe [this one](https://stackoverflow.com/questions/43617578/how-to-do-colored-2d-grid-with-3-arrays/43620435#43620435) or [this one](https://stackoverflow.com/questions/44987972/heatmap-with-matplotlib/44989996#44989996) are more helpful. (Oh and ignore my comment about imshow if the bins are unequally spaced) – ImportanceOfBeingErnest Nov 26 '18 at 21:01
  • Thank you @ImportanceOfBeingErnest I added the edit to the post - it just gives an empty plot - this was one of the many ways I tried before :( Am I just making a silly mistake? Also yes the bins are unequal! – Acyna Nov 26 '18 at 21:10
  • `reshape(x, (-1, 1))` makes no sense. I would suggest you spend more than 5 minutes understanding the linked posts. – ImportanceOfBeingErnest Nov 26 '18 at 21:14
  • @ImportanceOfBeingErnest Cheers, I've had a good look at your linked posts but they all talk about equal sized bins - and as in the comment below I have a bit of a problem reshaping z - > z.reshape( (len(x)**.5, len(x)**.5 ) throws up a value error and the way in the code was the only way I could reshape - as you mentioned I don't actually understand that way. I won't use it any more but I still can't reshape my z. Thanks for your help! --- Also my values are the edges of my rectangles – Acyna Nov 26 '18 at 21:35
  • I guess even without understanding it, you may directly use [this solution](https://stackoverflow.com/a/44989996/4124317). Of course that only applies if you get rid to the problem of having one value too much in your dataframe (for which we can't help without having the file available). – ImportanceOfBeingErnest Nov 26 '18 at 21:37
  • Relevant as well: https://stackoverflow.com/a/43536899/4124317 – ImportanceOfBeingErnest Nov 26 '18 at 21:57
  • However one thing I do not understand is why you would accept the answer below given that you put so much emphasis on the fact that you have unequal bins. – ImportanceOfBeingErnest Nov 26 '18 at 22:28
  • @ImportanceOfBeingErnest I don't know how to say that a comment on an answer is correct so I marked his answer instead to make sure he got credit. Though the answer is definitely not what worked, his final comments on his answer were great – Acyna Nov 27 '18 at 17:41

2 Answers2

0

Adapting the linked question to you problem, you should get:

import numpy as np
import matplotlib.pyplot as plt

x = list(range(10))*10
y = np.repeat(list(range(10)), 10)

# build random z data
z = np.multiply(x, y)

N = int(len(z)**.5)
Z = z.reshape(N, N)
plt.imshow(Z[::-1], extent=(np.amin(x), np.amax(x), np.amin(y), np.amax(y)), aspect = 'auto')

plt.show()
Silmathoron
  • 1,781
  • 1
  • 15
  • 32
  • Hey so this is the problem I was talking about in my code - for some reason I can't reshape my z data. (my z data is a np.ndarrayy) I get the error : ValueError: cannot reshape array of size 145 into shape (12,12) – Acyna Nov 26 '18 at 20:54
  • this is weird, you have one too many values... just use `z[1:]` or `z[:-1]` (and check how you made the data: you should have a perfect square) – Silmathoron Nov 26 '18 at 21:16
  • Thank you very much for continuing to try with this - unfortunately when I tried this it did the same as the edit in my post - gave a set of axes and a colour bar but a completely blank graph and no error. No idea what's going on. Also z is the same size as my x and y arrays so I also have no clue as to what's wrong there – Acyna Nov 26 '18 at 21:20
  • I couldn't find a nice way to upload it but I edited the image of the data (first link in post) to reflect the headers. I check through the csv and it is the same, just the same pattern of data ending on row 146 – Acyna Nov 26 '18 at 21:52
  • please drop the data [here](https://framadrop.org/) and I just saw something weird: your x and y data do not seem to be gridded (sizefrac 1 has tempbin max = -15.5 while sizefrac 2.5 has tempbin max -17.5...) – Silmathoron Nov 26 '18 at 22:04
  • 1
    Ahh you're right - when I mess around with the plot in other software the 'rectangles' are actually rhomboids - the top side starts and ends at different x value to the bottom side on the graph - I think I will have to spend some time thinking about how to get the rectangles to cover the whole x range instead of doing that - thank you – Acyna Nov 26 '18 at 22:09
  • if you can define them as quadrilateral corners, then you can indeed use the [pcolormesh function](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.pcolormesh.html) and don't forget "The dimensions of X and Y should be one greater than those of C" – Silmathoron Nov 26 '18 at 22:15
0

The answer was found by Silmathoron in a comment on his answer above - the answer above did not help but in the comments he noticed that the X,Y data was not gridded in w way which would create rectangles on the plot and also mentioned that Z needed to be one smaller than X and Y - from this I could fix my code - thanks all

Acyna
  • 3
  • 5