Why does pcolor not display the full matrix?
Show older comments
There are several questions on here asking why pcolor does not display the full matrix. Most answers say something along the lines of "use image/imagesc instead". And then other people jump in and say pcolor is more powerful (because it allows irregularly spaced grids). In my case, I use irregularly spaced grids to display geophysical modelling results so image/imagesc does not work. Some people suggest first interpolating your irregularly-spaced data and then using image/imagesc. But, for me, the actual x and y vectors matter a lot (e.g. the location of a given model cell is very important).
I understand that pcolor removes the right column and the top row.
My question is: Why does this happen? Is this a feature or a bug?
From the pcolor help:
"The grid covers the region X=1:n and Y=1:m, where [m,n] = size(C)."
Maybe I'm misunderstanding, but doesn't the grid cover the region X = 1:n-1 and Y=1:m-1? Why does it say it covers the full region if, in reality, it cuts off the top row and right column of the data matrix?
To me this is a bug that should be fixed and everyone seems to complain about it. But I figure there must be some deeper reason why it is not (or can't be) fixed.
Here's an example script:
%Some irregularly spaced vectors:
x = [0.5 0.8 1 1.6];
y = [1.2 1.4 2 2.2];
%Some data
r = ones(4,4); %Size = 4 by 5
r(1,1) = 3;
r(4,4) = 10;
r(2,2) = 10;
pcolor(x,y,r)
colorbar
% r(2,2) is in the correct spot
% and you can see r(1,1) as well.
% But you cannot see r(4,4) = 10
1 Comment
Just running the code from the OP to get a clearer understanding of the question.
%Some irregularly spaced vectors:
x = [0.5 0.8 1 1.6];
y = [1.2 1.4 2 2.2];
%Some data
r = ones(4,4); %Size = 4 by 5
r(1,1) = 3;
r(4,4) = 10;
r(2,2) = 10;
pcolor(x,y,r)
colorbar
% r(2,2) is in the correct spot
% and you can see r(1,1) as well.
% But you cannot see r(4,4) = 10
Answers (2)
Steven Lord
on 3 Dec 2020
1 vote
This is not a bug. The perceived bug is the result of the 2-dimensional fencepost error. From the description of the C input argument on the documentation page for the pcolor function:
"The values in C map colors in the colormap array to the vertices surrounding each face. The color of a face depends on the color at one of its four vertices. Of the four vertices, the one that come first in X and Y determines the color of the face. If you do not specify X and Y, MATLAB uses X=1:n and Y=1:m, where [m,n] = size(C). Because of this relationship between the vertex colors and face colors, none of the values in the last row and column of C are represented in the plot."
The values in C do not represent the colors of the faces but represent the colors of the vertices. If you look at the picture included in that input argument description the corresponding C is 3-by-3 but only the four (2-by-2) elements with arrows pointing to the faces are used in determining the colors of the pcolor plot. Similarly, if you wanted to draw a 9-by-9 Sudoku grid on a piece of paper you need to draw 10 horizontal and 10 vertical lines to fully enclose the 81 squares where numbers would be placed.
8 Comments
Darcy Cordell
on 3 Dec 2020
Walter Roberson
on 23 Feb 2021
Just make something like imagesc with variable data spacing, how hard can it be?
Use warp()
Paul
on 23 Feb 2021
Coincidentally, I just ran into this exact pcolor v. imagesc issue yesterday. pcolor returns a surface, which gives control over some things that imagesc does not, like EdgeColor.
Harri Ojanen
on 23 Oct 2023
Yet again running into this problem. IMHO this pcolor behaviour is a bug, even if it works as specified (i.e., the specification is wrong). This does not make any sense, why would anyone want it to work like it does?
imagesc is broken, because it does not respect the x and y vectors when those are not uniformly spaced. pcolor is broken as described by the OP. heatmap makes more sense, but has a completely differerent interface and other limitations, e.g., it is not possible to plot other graphics on top of the heatmap (at least hold on gives an error with heatmap).
They are all broken in various ways. I have to implement my own... Wait, someone has already done it, there is sanePColor in file exchange...
DGM
on 23 Oct 2023
It's not a fencepost error until someone starts arguing that the number of posts should equal the number of boards.
Lena
on 30 Jan 2026 at 4:51
For anybody else looking for quick fix, just make a n+1 x m+1 nan matrix and place your data (nxm) into this letting the last rows stay nan. Then when you plot pcolor those nan's are cut off and you are left with your data plotted
Can you illustrate your quick fix with the example from this question? I tried it, assuming that you mean to have the last row and column stay NaN, and the x and y vectors are both extended with a single NaN. But the result doesn't change.
%Some irregularly spaced vectors:
x = [0.5 0.8 1 1.6];
y = [1.2 1.4 2 2.2];
%Some data
r = ones(4,4); %Size = 4 by 5
r(1,1) = 3;
r(4,4) = 10;
r(2,2) = 10;
R = nan(5,5);
R(1:4,1:4) = r;
X = [x,NaN];
Y = [y,NaN];
pcolor(X,Y,R)
colorbar
@Lena As I intimated before, there's a conceptual difference between the fenceposts and boards. Disregarding whether your suggestion works as described, where do you propose the "fenceposts" (vertices as defined in the x,y data) exist in relation the the centroid of the "boards" (the face value of the image as mapped by the colormap)?
Remember that the face value of a pcolor() plot is interpolated based on the bounding z-values as defined strictly at the specified x,y coordinates. There are no z-values defined explicitly at the centers of the faces. The face values are all interpolated.
Again, pcolor() is as conceptually consistent as surf(). The x,y and z data all define the vertices of a mesh. If that's not what you want, you have to state what you propose to accomplish.
If it's a matter of suggesting that established function behaviors are inadequate, then I assert that the complaint shouldn't be that pcolor() is "wrong" but that image()/imagesc() should be extended to accept explicit xdata and ydata. Again, to be self-consistent, x,y data would define the face centers, not the mesh vertices. Which do we want?
c = [1, 2, 3; 4, 5, 6; 7, 8, 9];
x = [1, 2, 4];
y = [1, 3, 4];
H = pcolor(x, y, c);
Fine. PCOLOR does exactly, what it is wanted to do. The upper row and right colum of the data are not displayed with flat coloring:
disp(H.FaceColor)
But with interpolated colors, the value on the top and right matter:
H2 = pcolor(x, y, c, 'FaceColor', 'interp');
PCOLOR is a tool, which works as explained in the documentation. The ability to use it with as well flat as interpolated colors has the effect, that with flat colors a row and a column is ignored in the coloring. An alternativ would be to offer two different commands for the different shadings. MathWorks decided in one of the first releases (I assume 1984), that PCOLOR should handle both coloring methods.
Use a programming language to solve a problem. If there is a 2-way hammer like PCOLOR, it might look strange from one side. Instead of discussing, if this is nasty or a bug, just use it to create the wanted output as explained in the docs.
By the way: The code of PCOLOR contains the underlying SURFACE command, so it is easy to check how to call SURFACE directly to do exactly, what you want to do.
Categories
Find more on Graphics Performance in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


