Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a matrix whose dimensions are 26x26x3. For my assignment I have written a program which is using a Do loop (maxx=maxy=10,maxz=2):

 Do[
  n = 0;
  h=0.4;
  k = Table[
         If[a <= #1 <= a + h && b <= #2 <= b + h && c <= #3 <= c + h & @@ pts[[w, t]], 1, 0], 
         {w, 1, Length[pts]}, 
         {t, 1, Length[pts[[w]]]}
      ];
  pls = Plus @@@ k;
  For[i = 1, i <= Length[pls], i++, If[pls[[i]] > 0, n++]];
  n, 
  {a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}
]

At every iteration I get a new value for n and I have to assign it to the correct position of my matrix as efficiently and fast as possible. I don't have a counter. So, I am a bit confused. How can I solve this issue?

On the other hand, can I create a matrix by saving n at the end of the Do loop?

Any help is appreciated.

share|improve this question
    
What would the correct position be? –  ssch Jan 6 '13 at 16:06
    
@ssch Correct position : For example, first n will be positioned in the matrix at {1,1,1}; second n at {1,1,2} third n at {1,1,3} then y axes will change and fourth n will be positioned at {1,2,1} and so on.. –  cesm Jan 6 '13 at 16:19
    
Well with those values of h and maxx,maxy,maxz you'll just get 1587 values of n, so at best your result will be a 23*23*3 matrix. I'm not sure I understand what you are doing. Are you for each interval $[a,a+h] \times [b,b+h] \times [c,c+h]$ counting how many rows have at least one element inside? What dimensions do you expect for the resulting matrix? –  ssch Jan 6 '13 at 16:42
    
Could you make a small example matrix and the result you expect from that? –  ssch Jan 6 '13 at 16:43
    
@ssch Yes, you are right. The dimensions will be 23x23x3. Thanks. Is it possible to write a program that the values of n when c change will be assigned to values of z dimensions on that matrix? And the same for y and x axes. –  cesm Jan 6 '13 at 19:20

3 Answers 3

up vote 6 down vote accepted

I think this does what you require:

Total[Unitize[BinCounts[#, {1, maxx + h, h}, {1, maxy + h, h}, {1, maxz + h, h}]] & /@ pts]
share|improve this answer
    
Ah BinCounts, I knew there was some command I was forgetting :) –  ssch Jan 6 '13 at 18:27
    
Ohh, thanks! This does what I want at one line :) –  cesm Jan 6 '13 at 20:05

Here a illustrative example of assigning values, retaining your Do loop structure. It just has an incrementing count at the place where you could add your own calculation:-

maxx = 4; maxy = 3; maxz = 2;
k = Table[{a, b, c}, {a, 1, maxx}, {b, 1, maxy}, {c, 1, maxz}];
count = 1;
Do[k[[a, b, c]] = count++, {a, 1, maxx}, {b, 1, maxy}, {c, 1, maxz}]
MatrixForm[k]

enter image description here

share|improve this answer
    
But then you're disregarding the stepsize h, you could also just replace the Do with Table in the original code and get a matrix –  ssch Jan 6 '13 at 16:45
    
I assumed the OP specifically wanted to use Do. However, Do doesn't seem to support step size for multiple dimensions. Also, I couldn't see how a step size of 0.4 would work for stepping through a matrix. –  Chris Degnen Jan 6 '13 at 16:59

I'm still not quite sure what output you expect, but at least this might be a way forward:

maxx = 10;
maxy = 10;
maxz = 2;
h = 0.4;
pts = RandomReal[{1, 10}, {26, 26, 3}];

You can start by replacing Do with Table to store your calculated n values

AbsoluteTiming[out=Table[(* Same stuff as in your Do *)];]
(* 8.5 seconds *)
out//Dimensions
(* {23,23,3} *)

You can replace the whole thing with:

AbsoluteTiming[out = Table[
    Count[
      MemberQ[#,_?(a<=#[[1]]<=a+h&&b<=#[[2]]<=b+h&&c<=#[[3]]<=c+h&)]&/@pts
    ,True]
    , {a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}];]
(* 5.2 s *)

That counts (Count[...,True]) how many rows have at least one (MemberQ) good element.

Some speed increase can be gained by compiling the pattern test for MemberQ

inInterval = Compile[{a, b, c, h, {pt, _Real, 1}},
  a <= pt[[1]] <= a + h && b <= pt[[2]] <= b + h && c <= pt[[3]] <= c + h
  ]
AbsoluteTiming[out2 = Table[
  Count[MemberQ[#, _?(inInterval[a, b, c, h, #] &)] & /@ pts, True]
   ,{a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}];]
(* 3.5 s *)

check Count and MemberQ

3.5s still seems quite slow for this problem I expect someone to come up with a quicker solution :)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.