DiscretePlot3D: Part specification is neither a machine-sized integer nor a list of machine-sized integers

I want to plot a 3D histogram of a matrix and I am using this line:

DiscretePlot3D[lmat[[x, y]], {x, 1, 3}, {y, 1, 3}, ExtentSize -> Full]

where lmat is the matrix.
The output is correct, but I receive the following error line:

Part::pspec: Part specification x is neither a machine-sized integer nor a list of machine-sized integers. >>

Where am I making a mistake? The line doesn’t show up if I replace lmat[[x, y]] with a “standard” function such as Sin[x, y] or if I use a function defined by myself such as f[x_, y_] := Sin[x + y].

The line appear again if I use functions which involve matrices:

amat = {{1, -1, 0, 0}, {-1, 2, 0, -1}, {0, 0, 1, -1}, {0, -1, -1, 2}};
h[x_, y_] := amat[[x, y]]
DiscretePlot3D[h[x, y], {x, 1, 3}, {y, 1, 3}, ExtentSize -> Full]

=================

  

 

Welcome! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour and check the faqs! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign!
– Louis
Aug 29 ’15 at 10:22

=================

2 Answers
2

=================

I cannot reproduce the behavior you observe in my version of Mathematica (10.2 on Win7-64), so I assume that you might be working on an older version. It would be interesting if you could add your version and platform to your question for reference.

Nevertheless, in my opinion the problem seems to be that the plotting function is attempting to evaluate its argument symbolically first. At that stage xx and yy have not been assigned a numerical value yet, so Part (i.e. [[…]]) throws an error because only integers or lists can be used as part specifications.

DiscretePlot3D then proceeds with numerical evaluation by assigning appropriate values to xx and yy, which works fine and generates your plot.

You can force numerical evaluation with a user defined function:

f[x_?NumericQ, y_?NumericQ] := lmat[[x, y]]
DiscretePlot3D[f[x, y], {x, 1, 3}, {y, 1, 3}, ExtentSize -> Full]

Take a look at this FAQ for more details about the powers of NumeriQ:
User-defined functions, numerical approximation, and NumericQ.

More appropriately to your situation, and since Part is only supposed to work on integers, you can further restrict the function to evaluate only when the arguments are integers, as suggested by Guess Who It Is in a comment below:

f[x_Integer, y_Integer] := lmat[[x, y]]

  

 

Even better: since Part[] is not expected to deal with fractional arguments, just do f[x_Integer, y_Integer] := (* stuff *).
– J. M.♦
Aug 29 ’15 at 14:35

  

 

@Guess good point. I added that definition to the answer as well.
– MarcoB
Aug 29 ’15 at 14:51

Perhaps BarChart3D using the “Grid” option for ChartLayout may be more useful for your aim, e.g.

mat = {{1, -1, 0, 0}, {-1, 2, 0, -1}, {0, 0, 1, -1}, {0, -1, -1, 2}};
BarChart3D[mat, ChartLayout -> “Grid”,
ChartLabels -> {Range[4], Range[4]},
LabelingFunction -> (Placed[Style[#, Red, Bold], Above] &),
ChartStyle -> Blue]

or just ListPointPlot3D, e.g.

ListPointPlot3D[mat, Filling -> Axis, PlotStyle -> PointSize[0.02]]

  

 

I think that they are both good solutions, but can anyone explain me the origin of the error message I riceived?
– Francesco
Aug 29 ’15 at 13:43

  

 

@Francesco MarcoB has provided a clear answer…I have nothing to add…apologies for delay…timezones
– ubpdqn
Aug 29 ’15 at 23:07