2
$\begingroup$

I have developed the following code, which produces what I aim to obtain.

Clear[n, t, gBar, mat0, mat1];
SeedRandom[15];
n = 5;
t = 7;
gBar = 0.05;
mat0 = Array[RandomInteger[{1, 8}] &, {n,t}]; (* Cross-section (n) over time (t) *)
mat1 = Array[0 &, {n, t - 1}];
mat2 = Array[0 &, {n, n}];
Do[
  Do[
   If[Log[mat0[[i, j + 1]]/mat0[[i, j]]] > gBar, 
    mat1[[i, j]] = Log[mat0[[i, j + 1]]/mat0[[i, j]]]], {i, 1, n}
   ], {j, 1, t - 1}
  ];

desiredOutput = ReplacePart[mat2, {{2, _} -> 1, {3, _} -> 1}] 

First, I create a matrix of data (cross-section over time): called mat0. Then, for each row, I conduct a Log[] operation. If the outcome satisfies If statement, then I place the result of the operation to that row in mat1. Here are the resulting matrices, mat0 and mat1, respectively.

enter image description here

After the mat1 is fully created, then I conduct operations using each column. Find the positions of nonzero elements in the 1st column, for example (mat1[2,1] and mat1[3,1] and then create the matrix of desiredOutput in which 2nd and 3rd rows are all one and the rest of the matrix is zero as follows:

enter image description here

How can I make the above code more efficient and shorter?

EDIT 1

This edit does not change anything in the above formulation, but asks a related extension.

This additional code:

Clear[λ, ψ, mu, μ];
λ = 0.6;
ψ = 2;
mu = λ*(mat1[[All, 1]]/gBar)^ψ  (* the 1st column *)
μ = Table[{i, mu[[i]]}, {i, 1, n}]

gives me what I need. I can repeatedly calculate the code for each column in mat1, but it is not efficient to do so. Instead, for the integrity of my research problem, I like to incorporate this additional piece of code into the code given in the question before EDIT 1 and automate it for each column t in mat1.

Regards.

$\endgroup$
1
$\begingroup$

Using mat1 from Henrik's answer, alternative ways to get mat2 and mu:

ClearAll[m2]
m2[m_][k_] := ArrayPad[Transpose[{Unitize[m[[All, k]]]}], 
  {0, {Dimensions[m][[1]] - 1, 0}}, "Fixed"];
Row[MatrixForm /@ m2[mat1] /@ Range[4]] // TeXForm

$\tiny\left( \begin{array}{ccccc} 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ \end{array} \right)\left( \begin{array}{ccccc} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ \end{array} \right)\left( \begin{array}{ccccc} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ \end{array} \right)\left( \begin{array}{ccccc} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 & 1 \\ \end{array} \right)$

ClearAll[mu]
mu[m_][k_] := MapIndexed[{#2[[1]], #} &, λ*(m[[All, k]]/gBar)^ψ ] ;
Row[MatrixForm /@ mu[mat1] /@ Range[6]] // TeXForm

$\tiny\left( \begin{array}{cc} 1 & 0. \\ 2 & 39.4565 \\ 3 & 39.4565 \\ 4 & 0. \\ 5 & 0. \\ \end{array} \right)\left( \begin{array}{cc} 1 & 0. \\ 2 & 0. \\ 3 & 0. \\ 4 & 908.776 \\ 5 & 461.235 \\ \end{array} \right)\left( \begin{array}{cc} 1 & 230.886 \\ 2 & 770.496 \\ 3 & 75.1608 \\ 4 & 0. \\ 5 & 0. \\ \end{array} \right)\left( \begin{array}{cc} 1 & 0. \\ 2 & 0. \\ 3 & 0. \\ 4 & 0. \\ 5 & 115.309 \\ \end{array} \right)\left( \begin{array}{cc} 1 & 0. \\ 2 & 0. \\ 3 & 0. \\ 4 & 0. \\ 5 & 115.309 \\ \end{array} \right)\left( \begin{array}{cc} 1 & 39.4565 \\ 2 & 19.8626 \\ 3 & 0. \\ 4 & 621.67 \\ 5 & 0. \\ \end{array} \right)$

$\endgroup$
7
  • $\begingroup$ Really very neat. It is just what I asked for. Thank you and Henrik. $\endgroup$ Oct 16 '18 at 23:32
  • $\begingroup$ @Tugrul, my pleasure. Thank you for the accept. $\endgroup$
    – kglr
    Oct 16 '18 at 23:33
  • $\begingroup$ I think something is not right in the generation of 0 and 1 matrices. Your m2[m_] matrix should use columns of mat1 to generate 6 matrices of (n,n) dimension each. $\endgroup$ Oct 17 '18 at 0:17
  • $\begingroup$ Tugrul, mat1 is 5by6 and m2[mat1][k] generates a 5by6 matrix based on column k of mat1. I just displayed 4 of 6 matrices because 6 wouldn't fit on the page. $\endgroup$
    – kglr
    Oct 17 '18 at 0:20
  • $\begingroup$ Yes, I saw the 6 matrices and I understand why you did it that way. But my question is about the dimension of the 1 and 0 matrices. In the original question, the 1-0 matrix is (n,n) dimension, not (n,t-1). $\endgroup$ Oct 17 '18 at 0:26
2
$\begingroup$
  • Log is vectorized and should not be computed more often than needed.

  • Clip is also vectorized and can replace If here. This way, we also do not have to initialize the matrix mat1.

  • Unitize along with Part can help you to generate the second matrix. Also no initialization needed.

Check this out:

mat1 = With[{A = Log[mat0]},
   Clip[Subtract[A[[All, 2 ;;]], A[[All, ;; -2]]], {gBar, ∞}, {0., 0.}]
   ];

mat2 = ({
     ConstantArray[0., n],
     ConstantArray[1., n]
     })[[Unitize[mat1[[All, 1]]] + 1]];
$\endgroup$
10
  • $\begingroup$ Thank you very much. Given mat0 and gBar, I run your code, but it gives me the following message: Symbol called with 0 arguments, 1 argument is expected and ` the expression 1+Unitize[Symbol[]] cannot be used as a part specification. Can you tell me what the matrix mymat1 is? $\endgroup$ Oct 16 '18 at 17:14
  • $\begingroup$ I discovered mymat1. It is my mat1. Your code runs perfect... $\endgroup$ Oct 16 '18 at 17:25
  • 1
    $\begingroup$ Yeah. Sorry. Fixed it. And, of course, you're welcome. $\endgroup$ Oct 16 '18 at 17:46
  • $\begingroup$ Do you mind if I ask another related question? This extra question is not worth to formulate as a separate question. Please let me know. $\endgroup$ Oct 16 '18 at 18:56
  • 1
    $\begingroup$ Yeah, okay. If it is a short one... =) $\endgroup$ Oct 16 '18 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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