1

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]
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Francesco
  • 97
  • 3
  • 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!
    –  Aug 29 '15 at 10:22

2 Answers2

3

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 $x$ and $y$ 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 $x$ and $y$, 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]]
MarcoB
  • 67,153
  • 18
  • 91
  • 189
1

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] 

enter image description here

or just ListPointPlot3D, e.g.

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

enter image description here

ubpdqn
  • 60,617
  • 3
  • 59
  • 148
  • 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