# Create a cross-section, time series data set using Matrix operations

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

Clear[n, t, gBar, mat0, mat1];
SeedRandom;
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. 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: 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.

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

ClearAll[m2]
{0, {Dimensions[m][] - 1, 0}}, "Fixed"];
Row[MatrixForm /@ m2[mat1] /@ Range] // 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[], #} &, λ*(m[[All, k]]/gBar)^ψ ] ;
Row[MatrixForm /@ mu[mat1] /@ Range] // 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)$$

• Really very neat. It is just what I asked for. Thank you and Henrik. Oct 16 '18 at 23:32
• @Tugrul, my pleasure. Thank you for the accept.
– kglr
Oct 16 '18 at 23:33
• 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. Oct 17 '18 at 0:17
• 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.
– kglr
Oct 17 '18 at 0:20
• 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). Oct 17 '18 at 0:26
• 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]];

• 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? Oct 16 '18 at 17:14
• I discovered mymat1. It is my mat1. Your code` runs perfect... Oct 16 '18 at 17:25
• Yeah. Sorry. Fixed it. And, of course, you're welcome. Oct 16 '18 at 17:46
• 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. Oct 16 '18 at 18:56
• Yeah, okay. If it is a short one... =) Oct 16 '18 at 18:59