1
votes

I have my data in 3 columns, denoting the values of the x, y and z coordinates respectively. The x and y points are on a grid (may be non-uniform, as here):

x y z 

1 1 5
1 2 7
1 3 0
3 1 6
3 2 9
3 3 5
7 1 4
7 2 0
7 3 8

Now I want to use a MATLAB function like pcolor to make a 2D color plot of this data where the z values will be denoted by color. Unfortunately pcolor wants the data for the x and y coordinates either as vectors or as grid matrices, and the z data also in the form of a grid matrix, and will not except column data of this form.

I don't want to use any fitting or interpolation. I only want to rearrange the data I have here. How can I attain this?

3
Possible duplicate of How do I resize a matrix in MATLAB?. Your own answer to your question makes me think that the duplicate is valid.Andras Deak
@AndrasDeak whilst if his data is not in this fantastically simply [x,y] structure, you'd need something else entirely to make pcolor work, see my answer belowAdriaan
Note that you don't (and shouldn't) put the language name in your title like that: that's what tags are for!Andras Deak

3 Answers

3
votes

General purpose method using meshgrid and unique:

data = [1 1 5;
1 2 7;
1 3 0;
3 1 6;
3 2 9;
3 3 5;
7 1 4;
7 2 0;
7 3 8];
[tmpX1,~,tmpX3] = unique(data(:,1));
[tmpY1,~,tmpY3] = unique(data(:,2));
[X,Y] = meshgrid(tmpX1,tmpY1);
tmpZ = sub2ind(tmpX3,tmpY3); %// use the third output from unique as indices
Z = zeros(size(X)); %//preallocate Z
Z(tmpZ) = data(:,3); %// Use indices to fill the grid
pcolor(X,Y,Z)

The third output of unique can be used as an integer representation of the location within the [X,Y] grid. sub2ind function courtesy of András Deák

As opposed to @AbhranilDas's answer this solution works also if your data is not on a nice grid, e.g.

data = [1 1 5;
5 2 7;
1 3 0;
3 1 6;
3 2 9;
3 7 5;
7 1 4;
7 2 0;
4 3 8];

The OP's solution only works because the data when reshaped through column-major order becomes exactly the coordinate grids as output by meshgrid. Whenever your data is not that simple and nice, using reshape will get you a non-uniform coordinate matrix.

1
votes

If this is for plotting purposes, where run-time performance is not a concern, I wouldn't resort to any fancy indexing trickery that's hard to understand and maintain.

Instead, I'd like to recommend a good old for loop combined with imagesc:

data = [
1 1 5
1 2 7
1 3 0
3 1 6
3 2 9
3 3 5
7 1 4
7 2 0
7 3 8
];

plt_data = NaN(max(data(:,2)), max(data(:,1)));

% iterate over the rows
for xyz = data'
    plt_data(xyz(2), xyz(1)) = xyz(3);
end

imagesc(plt_data)
colorbar()

enter image description here

Okay, so if you have data with negative axis points, then it becomes more work:

data = [
1 -1 5
1 2 7
1 -3 1
3 1 6
-3 2 9
-3 -3 5
7 1 4
7 -2 1
7 3 8
];

x0 = min(data(:,1));
x1 = max(data(:,1));

y0 = min(data(:,2));
y1 = max(data(:,2));

xrange = x1 - x0;
yrange = y1 - y0;

plt_data = NaN(yrange, xrange);

% iterate over the rows
for xyz = data'
    plt_data(xyz(2)-y0+1, xyz(1)-x0+1) = xyz(3);
end

imagesc(x0:x1, y0:y1, plt_data)
set(gca(), 'ydir', 'normal')
colorbar()

And you'll probably want to flip the y-axis so it looks like a familiar Cartesian axis:

enter image description here

0
votes
X=reshape(data(:,1), [3 3]);
Y=reshape(data(:,2), [3 3]);
Z=reshape(data(:,3), [3 3]);

pcolor(X,Y,Z);

Note: this will produce a matrix with 4 colours instead of nine because pcolor drops a row and column, but that's a different issue.