0
$\begingroup$

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.

$\endgroup$
7
  • $\begingroup$ What would the correct position be? $\endgroup$
    – ssch
    Jan 6, 2013 at 16:06
  • $\begingroup$ @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.. $\endgroup$
    – cesm
    Jan 6, 2013 at 16:19
  • $\begingroup$ 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? $\endgroup$
    – ssch
    Jan 6, 2013 at 16:42
  • $\begingroup$ Could you make a small example matrix and the result you expect from that? $\endgroup$
    – ssch
    Jan 6, 2013 at 16:43
  • $\begingroup$ @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. $\endgroup$
    – cesm
    Jan 6, 2013 at 19:20

3 Answers 3

6
$\begingroup$

I think this does what you require:

Total[Unitize[BinCounts[#, {1, maxx + h, h}, {1, maxy + h, h}, {1, maxz + h, h}]] & /@ pts]
$\endgroup$
2
  • $\begingroup$ Ah BinCounts, I knew there was some command I was forgetting :) $\endgroup$
    – ssch
    Jan 6, 2013 at 18:27
  • $\begingroup$ Ohh, thanks! This does what I want at one line :) $\endgroup$
    – cesm
    Jan 6, 2013 at 20:05
4
$\begingroup$

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 :)

$\endgroup$
2
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ 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 $\endgroup$
    – ssch
    Jan 6, 2013 at 16:45
  • $\begingroup$ 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. $\endgroup$ Jan 6, 2013 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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