Chapter 1 Data Structures

1.1 Matrices and Arrays

1.1.1 Array Reshape, Repeat and Expand Examples

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.1.1 Basic Examples of Reshape

a = [1,2,3,4,5,6]';
b = reshape(a, [3,2])

b = 3x2    
     1     4
     2     5
     3     6

b(:)

ans = 6x1    
     1
     2
     3
     4
     5
     6

a = [1,2,3;4,5,6;7,8,9;10,11,12]'

a = 3x4    
     1     4     7    10
     2     5     8    11
     3     6     9    12

b = reshape(a, [6,2])

b = 6x2    
     1     7
     2     8
     3     9
     4    10
     5    11
     6    12

1.1.1.2 Stack Two Matrix of Equal Column Count Together

a = [1,2;3,4];
a_stacked = [a;a;a];
disp(a_stacked);

     1     2
     3     4
     1     2
     3     4
     1     2
     3     4

1.1.1.3 Repeat/Duplicate Matrix Downwards

There is a 2 by 3 matrix, to be repeated 4 times, downwards. This is useful for replicating data matrix for say counterfactual purposes.

Below, we have two ways of repeating a matrix downwards. Copy as whole, or copy row by row.

row_count = 2;
col_count = 3;
repeat_mat_count = 2;

data_vec = 1:(row_count*col_count);
searchMatrix = reshape(data_vec,row_count,col_count);

% To repeat matrix downwards
rep_rows_idx = [1:row_count]'*ones(1,repeat_mat_count);
rep_rows_idx = rep_rows_idx(:);

rep_cols_idx = [1:col_count];
rep_cols_idx = rep_cols_idx(:);

searchMatrixRep_stack = searchMatrix(rep_rows_idx, rep_cols_idx);

% To insert repeated rows following original rows
rep_rows_idx = ([1:row_count]'*ones(1,repeat_mat_count))';
rep_rows_idx = rep_rows_idx(:);

searchMatrixRep_dup = searchMatrix(rep_rows_idx, rep_cols_idx);

disp(searchMatrix)

     1     3     5
     2     4     6

disp(searchMatrixRep_stack)

     1     3     5
     2     4     6
     1     3     5
     2     4     6

disp(searchMatrixRep_dup)

     1     3     5
     1     3     5
     2     4     6
     2     4     6

1.1.1.4 Index Dimension Transform

it_inner_fin = 5; it_outter_fin = 3;

it_inner_cur = it_outter_fin it_outter_cur = it_inner_fin

ar_it_cols_idx = 1:1:(it_inner_fin*it_outter_fin) ar_it_cols_inner_dim = repmat(1:it_inner_cur, \[it_outter_cur, 1\]) ar_it_cols_inner_dim(:)’

mt_it_cols_idx = reshape(ar_it_cols_idx, \[it_inner_cur, it_outter_cur\])’ mt_it_cols_idx(:)’

it_inner_fin = 5;
it_outter_fin = 3;

ar_it_cols_idx = 1:1:(it_inner_fin*it_outter_fin)

ar_it_cols_idx = 1x15    
     1     2     3     4     5     6     7     8     9    10    11    12    13    14    15

mt_it_cols_idx = reshape(ar_it_cols_idx, [it_outter_fin, it_inner_fin])'

mt_it_cols_idx = 5x3    
     1     2     3
     4     5     6
     7     8     9
    10    11    12
    13    14    15

mt_it_cols_idx(:)'

ans = 1x15    
     1     4     7    10    13     2     5     8    11    14     3     6     9    12    15

1.1.2 Array Index Slicing and Subsetting to Replace and Expand

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.2.1 Find the First Negative Element of Array

There is an array with positive, negative and NaN values, find the first negative number’s index, and the last positive number index. Use the find function.

for it_array=1:1:2
    % Construct Array
    if (it_array == 1) 
        ar_alpha_sum_devi_one = [0.1, 0.7, -0.001, NaN, NaN];
    elseif (it_array ==2)
        ar_alpha_sum_devi_one = [0.1, 0.7, 0.001, NaN, NaN];
    end
    % Find last positive
    it_last_pos_idx = find(ar_alpha_sum_devi_one > 0, 1, 'last');
    % Find first negative
    it_first_neg_idx = find(ar_alpha_sum_devi_one < 0, 1, 'first');
    if (isempty(it_first_neg_idx))
        it_first_neg_idx = NaN;
    end
    disp(['it_last_pos_idx=' num2str(it_last_pos_idx) ...
        ', it_first_neg_idx=' num2str(it_first_neg_idx)])
end

it_last_pos_idx=2, it_first_neg_idx=3
it_last_pos_idx=3, it_first_neg_idx=NaN

1.1.2.2 First the First Negative Element of Last Segment of Array

There is an array with some negative numbers, then some positive numbers, then some negative numbers again. Find the first element of the final segment of negative numbers.

for it_array=1:5
    
    % Construct Array
    if (it_array == 1) 
        ar_alpha_sum_devi_one = [0.1, 0.7, -0.001, NaN, NaN];
    elseif (it_array ==2)
        ar_alpha_sum_devi_one = [0.1, 0.7, 0.001, NaN, NaN];
    elseif (it_array ==3)
        ar_alpha_sum_devi_one = [-0.001, 0.1, 0.7, 0.001, NaN, NaN];
    elseif (it_array ==4)
        ar_alpha_sum_devi_one = [-0.001, 0.1, 0.7, 0.001, -0.0002, -0.05, NaN, NaN];
    elseif (it_array ==5)
        ar_alpha_sum_devi_one = [NaN, NaN, -0.001, 0.1, 0.7, 0.001, -0.0002, NaN];
    end
    
    % Find last positive
    it_last_pos_idx = find(ar_alpha_sum_devi_one > 0, 1, 'last');
    % Find first negative
    it_first_neg_idx = find(ar_alpha_sum_devi_one < 0, 1, 'first');
    % Find first negative of last negative segment
    ar_alpha_sum_after_last_pos = ...
        ar_alpha_sum_devi_one(it_last_pos_idx:length(ar_alpha_sum_devi_one));
    it_first_neg_last_neg_seg_idx = it_last_pos_idx - 1 + ...
        find(ar_alpha_sum_after_last_pos < 0, 1, 'first');
    
    if (isempty(it_first_neg_idx))
        it_first_neg_idx = NaN;
    end
    if (isempty(it_first_neg_last_neg_seg_idx))
        it_first_neg_last_neg_seg_idx = NaN;
    end
    
    disp(['it_last_pos_idx=' num2str(it_last_pos_idx) ...
        ', it_first_neg_idx=' num2str(it_first_neg_idx)... 
        ', it_first_neg_last_neg_seg_idx=' num2str(it_first_neg_last_neg_seg_idx)])
end

it_last_pos_idx=2, it_first_neg_idx=3, it_first_neg_last_neg_seg_idx=3
it_last_pos_idx=3, it_first_neg_idx=NaN, it_first_neg_last_neg_seg_idx=NaN
it_last_pos_idx=4, it_first_neg_idx=1, it_first_neg_last_neg_seg_idx=NaN
it_last_pos_idx=4, it_first_neg_idx=1, it_first_neg_last_neg_seg_idx=5
it_last_pos_idx=6, it_first_neg_idx=3, it_first_neg_last_neg_seg_idx=7

1.1.2.3 Index Select Rows and Columns of a 2D matrix

In the example below, select by entire rows and columns:

% There is a 2D Matrix
rng(123);
randMatZ = rand(3,6);
disp(randMatZ);

    0.6965    0.5513    0.9808    0.3921    0.4386    0.7380
    0.2861    0.7195    0.6848    0.3432    0.0597    0.1825
    0.2269    0.4231    0.4809    0.7290    0.3980    0.1755

% Duplicate Select Row sand Columns of Elements
disp(randMatZ([1,2,3,3,3,2], [1,1,2,2,2,1]))

    0.6965    0.6965    0.5513    0.5513    0.5513    0.6965
    0.2861    0.2861    0.7195    0.7195    0.7195    0.2861
    0.2269    0.2269    0.4231    0.4231    0.4231    0.2269
    0.2269    0.2269    0.4231    0.4231    0.4231    0.2269
    0.2269    0.2269    0.4231    0.4231    0.4231    0.2269
    0.2861    0.2861    0.7195    0.7195    0.7195    0.2861

1.1.2.4 Index Select Set of Elements from 2D matrix

Rather than selecting entire rows and columns, suppose we want to select only one element at row 1 col 2, the element at row 2 col 4, element at row 5 col 1, etc.

% Select Subset of Elements
it_row_idx = [1,2,3,1,3,2];
it_col_idx = [1,1,5,4,2,3];
% Select sub2idx
ar_lin_idx = sub2ind(size(randMatZ), it_row_idx, it_col_idx);
ar_sel_val = randMatZ(ar_lin_idx);
disp(ar_sel_val');

    0.6965
    0.2861
    0.3980
    0.3921
    0.4231
    0.6848

1.1.2.5 Find Closest Element of Array to Each Element of Another Array

Given scalar value, find the cloest value in array:

fl_a = 3.4;
ar_bb = [1,2,3,4];
[fl_min, it_min_idx] = min(abs(ar_bb-fl_a));
disp(it_min_idx);

     3

Given a scalar value and an array, find the closest smaller value in the array to the scalar value:

fl_a = 2.1;
ar_bb = [1,2,3,4];
disp(sum(ar_bb<fl_a));

     2

Array A is between 0 and 1, on some grid. Array B is also between 0 and 1, but scattered. Find for each element of B the index of the cloest value on A that is smaller than the element in B.

rng(1234);
ar_a = linspace(0,10,5);
ar_b = rand([5,1])*10;
mt_a_less_b = ar_a<ar_b;
mt_a_less_b_idx = sum(ar_a<ar_b, 2);
disp(ar_a);

         0    2.5000    5.0000    7.5000   10.0000

disp(ar_b);

    1.9152
    6.2211
    4.3773
    7.8536
    7.7998

disp(mt_a_less_b);

   1   0   0   0   0
   1   1   1   0   0
   1   1   0   0   0
   1   1   1   1   0
   1   1   1   1   0

disp(mt_a_less_b_idx);

     1
     3
     2
     4
     4

1.1.2.6 Matlab Index based Replacement of Subset of Matrix Values

rng(123);
randMatZ = rand(3,6)+1;
randMat = rand(3,6)-0.5;
 
output = max(-randMat,0);
randMatZ(output==0) = 999;
min(randMatZ,[],2);
 randMatZ((max(-randMat,0))==0) = 999;
disp(randMatZ);

  999.0000  999.0000  999.0000    1.3921    1.4386    1.7380
  999.0000  999.0000    1.6848    1.3432    1.0597    1.1825
  999.0000  999.0000    1.4809  999.0000    1.3980    1.1755

disp(min(randMatZ,[],2));

    1.3921
    1.0597
    1.1755

1.1.2.7 Matlab Matrix Index Based Matrix Expansion (Manual)

In the example below, we start with a 4 by 2 matrix, than we expand specific rows and columns of the matrix. Specifically, we expand the matrix such that the result matrix repeats the 1st, 2nd, 1st, 2nd, then 3rd, than 1st, 1st, and 1st rows. And repeats column 1, then 2nd, then 2nd, then 2nd, and finally the first column.

% Original Matrix
Z = 2;
N = 2;
Q = 2;
base_mat = reshape(1:(Z*N*Q),Z*N,Q);
disp(base_mat);

     1     5
     2     6
     3     7
     4     8

% Expanded Matrix
base_expand = base_mat([1,2,1,2,3,1,1,1],[1,2,2,2,1]);
disp(base_expand);

     1     5     5     5     1
     2     6     6     6     2
     1     5     5     5     1
     2     6     6     6     2
     3     7     7     7     3
     1     5     5     5     1
     1     5     5     5     1
     1     5     5     5     1

1.1.2.8 Duplicate Matrix Downwards N times Using Index

The example here has the same idea, but we do the operations above in a more automated way. This could be done using alternative methods.

% Original Matrix
Z = 2;
N = 2;
Q = 2;
base_mat = reshape(1:(Z*N*Q),Z*N,Q);
disp(base_mat);

     1     5
     2     6
     3     7
     4     8

% Generate row Index many times automatically depending on how many times
% to replicate
vmat_repeat_count = 3;
vmat_reindex_rows_repeat = [1:(Z*N)]'* ones(1,vmat_repeat_count);
vmat_reindex_rows_repeat = vmat_reindex_rows_repeat(:);
disp(vmat_reindex_rows_repeat');

     1     2     3     4     1     2     3     4     1     2     3     4

% Duplicate Matrix by the Rows specified above, and using the same number
% of columns.
mat_repdown = base_mat(vmat_reindex_rows_repeat(:), 1:Q);
disp(mat_repdown');

     1     2     3     4     1     2     3     4     1     2     3     4
     5     6     7     8     5     6     7     8     5     6     7     8

1.1.2.9 Given ND Array, Get Row and Column (and other dimension) Index With Value Conditioning

There is a matrix where some values are equal to 1 (based on some prior selection), get the row and column index of the matrix.

% Some matrix with 1s
rng(123);
mt_some_ones = rand(3,3);
disp(mt_some_ones);

    0.6965    0.5513    0.9808
    0.2861    0.7195    0.6848
    0.2269    0.4231    0.4809

% find the location of the ones
[r_idx, c_idx] = find(mt_some_ones<0.5);
% the set of locations
disp([r_idx,c_idx]);

     2     1
     3     1
     3     2
     3     3

Now do the same three with a three dimensional array:

% Some matrix with 1s
rng(123);
mn3_some_ones = rand(3,3,3);
disp(mn3_some_ones);

(:,:,1) =

    0.6965    0.5513    0.9808
    0.2861    0.7195    0.6848
    0.2269    0.4231    0.4809


(:,:,2) =

    0.3921    0.4386    0.7380
    0.3432    0.0597    0.1825
    0.7290    0.3980    0.1755


(:,:,3) =

    0.5316    0.8494    0.7224
    0.5318    0.7245    0.3230
    0.6344    0.6110    0.3618

% find the location of the ones
[d1_idx, d2_idx, d3_idx] = ind2sub(size(mn3_some_ones), find(mn3_some_ones<0.5));
% the set of locations
disp([d1_idx, d2_idx, d3_idx]);

     2     1     1
     3     1     1
     3     2     1
     3     3     1
     1     1     2
     2     1     2
     1     2     2
     2     2     2
     3     2     2
     2     3     2
     3     3     2
     2     3     3
     3     3     3

1.1.2.10 Max of Matrix column by Column Linear to 2d Index

Finding max of matrix column by column, then obtain the linear index associated with the max values.

randMat = rand(5,3);
disp(randMat);

    0.2283    0.4309    0.8934
    0.2937    0.4937    0.9442
    0.6310    0.4258    0.5018
    0.0921    0.3123    0.6240
    0.4337    0.4264    0.1156

[maxVal maxIndex] = max(randMat);
linearIndex = sub2ind(size(randMat),maxIndex,(1:1:size(randMat,2)))

linearIndex = 1x3    
     3     7    12

randMat(linearIndex)

ans = 1x3    
    0.6310    0.4937    0.9442

t_pV = [1,2;3,4;5,6];
t_pV_Ind = [1,1;0,0;1,1];
[maxVal maxIndex] = max(t_pV(t_pV_Ind==1))

maxVal = 6
maxIndex = 4

1.1.2.11 Given Array of size M, Select N somewhat equi-distance elements

% Subset count
it_n = 5;

% Example 1, long array
ar_fl_a = 1:1.1:100;
ar_it_subset_idx = unique(round(((0:1:(it_n-1))/(it_n-1))*(length(ar_fl_a)-1)+1));
ar_fl_a_subset = ar_fl_a(ar_it_subset_idx);
disp(ar_fl_a_subset);

    1.0000   26.3000   50.5000   75.8000  100.0000


% Example 2, Short Array
ar_fl_a = 1:1.1:3;
ar_it_subset_idx = unique(round(((0:1:(it_n-1))/(it_n-1))*(length(ar_fl_a)-1)+1));
ar_fl_a_subset = ar_fl_a(ar_it_subset_idx);
disp(ar_fl_a_subset);

    1.0000    2.1000


% Write As function
f_subset = @(it_subset_n, it_ar_n) unique(round(((0:1:(it_subset_n-1))/(it_subset_n-1))*(it_ar_n-1)+1));

% Select 5 out of 10
disp(f_subset(5, 10));

     1     3     6     8    10


% Select 10 out of 5
disp(f_subset(10, 5));

     1     2     3     4     5


% Select 5 out of 5
disp(f_subset(5, 5));

     1     2     3     4     5

1.1.3 Maximum of Matrix Columns, Sort Matrix Columns

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.3.1 Max Value from a Matrix

Given a matrix of values, what is the maximum element, what are the row and column indexes of this max element of the matrix.

rng(123);
N = 3;
M = 4;
mt_rand = rand(M,N);
disp(mt_rand);

    0.6965    0.7195    0.4809
    0.2861    0.4231    0.3921
    0.2269    0.9808    0.3432
    0.5513    0.6848    0.7290

[max_val, max_idx] = max(mt_rand(:));
[max_row, max_col] = ind2sub(size(mt_rand), max_idx)

max_row = 3
max_col = 2

1.1.3.2 MAX Value from Each Column

There is a matrix with N columns, and M rows, with numerical values. Generate a table of sorted index, indicating in each column which row was the highest in value, second highest, etc. (1) sort each column. (2) show the row number from descending or ascending sort for each column as a matrix.

% Create a 2D Array
rng(123);
N = 2;
M = 4;
mt_rand = rand(M,N);
disp(mt_rand);

    0.6965    0.7195
    0.2861    0.4231
    0.2269    0.9808
    0.5513    0.6848

Use the maxk function to generate sorted index:

% maxk function
[val, idx] = max(mt_rand);
disp(val);

    0.6965    0.9808

disp(idx);

     1     3

1.1.3.3 MAXK Sorted Sorted Index for Each Column of Matrix

There is a matrix with N columns, and M rows, with numerical values. Generate a table of sorted index, indicating in each column which row was the highest in value, second highest, etc. (1) sort each column. (2) show the row number from descending or ascending sort for each column as a matrix.

% Create a 2D Array
rng(123);
N = 2;
M = 4;
mt_rand = rand(M,N);
disp(mt_rand);

    0.6965    0.7195
    0.2861    0.4231
    0.2269    0.9808
    0.5513    0.6848

Use the maxk function to generate sorted index:

% maxk function
[val, idx] = maxk(mt_rand, M);
disp(val);

    0.6965    0.9808
    0.5513    0.7195
    0.2861    0.6848
    0.2269    0.4231

disp(idx);

     1     3
     4     1
     2     4
     3     2

1.1.4 Array Broadcast and Expansion Examples

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

Matrix broadcasting was added to matlab’s recent editions. This is an important step for vectorizing codes. Proper usage of broadcasting reduces memory allocation requirements for matrix matrix operations.

1.1.4.1 Broadcasting with A Row and a Column

Below we add together a 1 by 3 and 4 by 1 array, that should not work. With broadcasting, it is assumed that we will mesh the arrays and then sum up the meshed matrixes.

clear all
ar_A = [1,2,3];
ar_B = [4,3,2,1]';
disp(size(ar_A));

     1     3

disp(size(ar_B));

     4     1

mt_A_B_broadcast = ar_A + ar_B;
disp(mt_A_B_broadcast);

     5     6     7
     4     5     6
     3     4     5
     2     3     4

mt_A_B_broadcast_product = ar_A.*ar_B;
disp(mt_A_B_broadcast_product);

     4     8    12
     3     6     9
     2     4     6
     1     2     3

1.1.4.2 Broadcasting with One Row and One Matrix

Below we add together a 1 by 3 and 4 by 3 matrix, that should not work. With broadcasting, it is assumed that we will repeat the array four times, duplicating the single row four times, so the matrix dimensions match up.

clear all
ar_A = [1,2,3];
mt_B = [4,3,2,1;5,4,3,2;6,5,4,3]';
disp(size(ar_A));

     1     3

disp(size(mt_B));

     4     3

mt_A_B_broadcast = ar_A + mt_B;
disp(mt_A_B_broadcast);

     5     7     9
     4     6     8
     3     5     7
     2     4     6

mt_A_B_broadcast_product = ar_A.*mt_B;
disp(mt_A_B_broadcast_product);

     4    10    18
     3     8    15
     2     6    12
     1     4     9

1.1.4.3 Broadcasting with One Column and One Matrix

Below we add together a 4 by 1 and 4 by 3 matrix, that should not work. With broadcasting, it is assumed that we will repeat the column three times, duplicating the single column three times, so the matrix dimensions match up.

clear all
ar_A = [4,3,2,1]';
mt_B = [4,3,2,1;5,4,3,2;6,5,4,3]';
disp(size(ar_A));

     4     1

disp(size(mt_B));

     4     3

mt_A_B_broadcast = ar_A + mt_B;
disp(mt_A_B_broadcast);

     8     9    10
     6     7     8
     4     5     6
     2     3     4

mt_A_B_broadcast_product = ar_A.*mt_B;
disp(mt_A_B_broadcast_product);

    16    20    24
     9    12    15
     4     6     8
     1     2     3

1.1.4.4 Expand with Broadcast, Percentage Choice grids

clear all
ar_w_perc = [0.1,0.5,0.9]

ar_w_perc = 1x3    
    0.1000    0.5000    0.9000

ar_w_level = [-2,0,2]

ar_w_level = 1x3    
    -2     0     2

fl_b_bd = -4

fl_b_bd = -4

ar_k_max = ar_w_level - fl_b_bd

ar_k_max = 1x3    
     2     4     6

ar_ak_perc = [0.1,0.3,0.7,0.9]

ar_ak_perc = 1x4    
    0.1000    0.3000    0.7000    0.9000

mt_k = (ar_k_max'*ar_ak_perc)'

mt_k = 4x3    
    0.2000    0.4000    0.6000
    0.6000    1.2000    1.8000
    1.4000    2.8000    4.2000
    1.8000    3.6000    5.4000

mt_a = (ar_w_level - mt_k)

mt_a = 4x3    
   -2.2000   -0.4000    1.4000
   -2.6000   -1.2000    0.2000
   -3.4000   -2.8000   -2.2000
   -3.8000   -3.6000   -3.4000

1.1.4.5 Expand Matrix Twice

clear all
% Same as above
ar_w_level = [-2,-1,-0.1]

ar_w_level = 1x3    
   -2.0000   -1.0000   -0.1000

fl_b_bd = -4

fl_b_bd = -4

ar_k_max = ar_w_level - fl_b_bd

ar_k_max = 1x3    
    2.0000    3.0000    3.9000

ar_ak_perc = [0.001, 0.1,0.3,0.7,0.9, 0.999]

ar_ak_perc = 1x6    
    0.0010    0.1000    0.3000    0.7000    0.9000    0.9990

mt_k = (ar_k_max'*ar_ak_perc)'

mt_k = 6x3    
    0.0020    0.0030    0.0039
    0.2000    0.3000    0.3900
    0.6000    0.9000    1.1700
    1.4000    2.1000    2.7300
    1.8000    2.7000    3.5100
    1.9980    2.9970    3.8961

mt_a = (ar_w_level - mt_k)

mt_a = 6x3    
   -2.0020   -1.0030   -0.1039
   -2.2000   -1.3000   -0.4900
   -2.6000   -1.9000   -1.2700
   -3.4000   -3.1000   -2.8300
   -3.8000   -3.7000   -3.6100
   -3.9980   -3.9970   -3.9961


% fraction of borrowing for bridge loan
ar_coh_bridge_perc = [0, 0.5, 0.999];

% Expand matrix to include coh percentage dimension
mt_k = repmat(mt_k, [1, length(ar_coh_bridge_perc)])

mt_k = 6x9    
    0.0020    0.0030    0.0039    0.0020    0.0030    0.0039    0.0020    0.0030    0.0039
    0.2000    0.3000    0.3900    0.2000    0.3000    0.3900    0.2000    0.3000    0.3900
    0.6000    0.9000    1.1700    0.6000    0.9000    1.1700    0.6000    0.9000    1.1700
    1.4000    2.1000    2.7300    1.4000    2.1000    2.7300    1.4000    2.1000    2.7300
    1.8000    2.7000    3.5100    1.8000    2.7000    3.5100    1.8000    2.7000    3.5100
    1.9980    2.9970    3.8961    1.9980    2.9970    3.8961    1.9980    2.9970    3.8961

mt_a = repmat(mt_a, [1, length(ar_coh_bridge_perc)])

mt_a = 6x9    
   -2.0020   -1.0030   -0.1039   -2.0020   -1.0030   -0.1039   -2.0020   -1.0030   -0.1039
   -2.2000   -1.3000   -0.4900   -2.2000   -1.3000   -0.4900   -2.2000   -1.3000   -0.4900
   -2.6000   -1.9000   -1.2700   -2.6000   -1.9000   -1.2700   -2.6000   -1.9000   -1.2700
   -3.4000   -3.1000   -2.8300   -3.4000   -3.1000   -2.8300   -3.4000   -3.1000   -2.8300
   -3.8000   -3.7000   -3.6100   -3.8000   -3.7000   -3.6100   -3.8000   -3.7000   -3.6100
   -3.9980   -3.9970   -3.9961   -3.9980   -3.9970   -3.9961   -3.9980   -3.9970   -3.9961

mt_a = mt_a

mt_a = 6x9    
   -2.0020   -1.0030   -0.1039   -2.0020   -1.0030   -0.1039   -2.0020   -1.0030   -0.1039
   -2.2000   -1.3000   -0.4900   -2.2000   -1.3000   -0.4900   -2.2000   -1.3000   -0.4900
   -2.6000   -1.9000   -1.2700   -2.6000   -1.9000   -1.2700   -2.6000   -1.9000   -1.2700
   -3.4000   -3.1000   -2.8300   -3.4000   -3.1000   -2.8300   -3.4000   -3.1000   -2.8300
   -3.8000   -3.7000   -3.6100   -3.8000   -3.7000   -3.6100   -3.8000   -3.7000   -3.6100
   -3.9980   -3.9970   -3.9961   -3.9980   -3.9970   -3.9961   -3.9980   -3.9970   -3.9961


% bridge loan component of borrowing
ar_brdige_a = (ar_coh_bridge_perc'*ar_w_level)'

ar_brdige_a = 3x3    
         0   -1.0000   -1.9980
         0   -0.5000   -0.9990
         0   -0.0500   -0.0999

ar_brdige_a = ar_brdige_a(:)'

ar_brdige_a = 1x9    
         0         0         0   -1.0000   -0.5000   -0.0500   -1.9980   -0.9990   -0.0999


% borrowing choices excluding bridge loan
mt_a_nobridge = mt_a - ar_brdige_a

mt_a_nobridge = 6x9    
   -2.0020   -1.0030   -0.1039   -1.0020   -0.5030   -0.0539   -0.0040   -0.0040   -0.0040
   -2.2000   -1.3000   -0.4900   -1.2000   -0.8000   -0.4400   -0.2020   -0.3010   -0.3901
   -2.6000   -1.9000   -1.2700   -1.6000   -1.4000   -1.2200   -0.6020   -0.9010   -1.1701
   -3.4000   -3.1000   -2.8300   -2.4000   -2.6000   -2.7800   -1.4020   -2.1010   -2.7301
   -3.8000   -3.7000   -3.6100   -2.8000   -3.2000   -3.5600   -1.8020   -2.7010   -3.5101
   -3.9980   -3.9970   -3.9961   -2.9980   -3.4970   -3.9461   -2.0000   -2.9980   -3.8962

1.1.5 Grid States, Choices and Optimal Choices Example

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.5.1 Generate State Grid

There many multiple individuals, each individual’s value for each state space variable is different. We duplicate that by shockCount and choicecount:

stateCount = 2;
shockCount = 3;
choiceCount = 4;

state1 = rand(1,stateCount)

state1 = 1x2    
    0.0571    0.6694

states1ShkDup = state1(ones(shockCount*choiceCount,1),:)

states1ShkDup = 12x2    
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694
    0.0571    0.6694

states1ShkDup(:)

ans = 24x1    
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571
    0.0571

1.1.5.2 Generate Choices

Generate Choice Grid, Example: Each individual has minimal protein and maximal protein they can get Generate a evenly set grid of choices for each individual from min to max. Individual min and max choice is a function of some component of their state-space, such as wealth/income level, and choice is the quantity of good to purchase.

stateCount = 2;
shockCount = 3;
choiceCount = 4;

% 1. Min and Max Choices for each state
minprot_n = floor(rand(1,stateCount)*10)

minprot_n = 1x2    
     7     7

maxprot_n = minprot_n + floor(rand(1,stateCount)*10)

maxprot_n = 1x2    
    14    12

% 2. Choice Ratios, ratios of max-min difference
protChoiceGrid = linspace(0,1,choiceCount)

protChoiceGrid = 1x4    
         0    0.3333    0.6667    1.0000

% 3. Each column is a different state.
searchMatrix = (protChoiceGrid'*(maxprot_n-minprot_n)+minprot_n(ones(choiceCount,1),:))

searchMatrix = 4x2    
    7.0000    7.0000
    9.3333    8.6667
   11.6667   10.3333
   14.0000   12.0000

% 4. Each column is a different state, each set of rows is a different shock% for the state. In this structure, shocks (to preference for example), do% not change choice grid for a given state
searchMatrix = searchMatrix([1:choiceCount]'* ones(1,shockCount), [1:stateCount]' * ones(1,1))

searchMatrix = 12x2    
    7.0000    7.0000
    9.3333    8.6667
   11.6667   10.3333
   14.0000   12.0000
    7.0000    7.0000
    9.3333    8.6667
   11.6667   10.3333
   14.0000   12.0000
    7.0000    7.0000
    9.3333    8.6667

searchMatrix(:)

ans = 24x1    
    7.0000
    9.3333
   11.6667
   14.0000
    7.0000
    9.3333
   11.6667
   14.0000
    7.0000
    9.3333

1.1.5.3 Average Utility over Shocks

Average of Shocks, E(value) For each STATE and CHOICE, x number of shocks. Need to average over shocks; The raw value output is: STATES * SHOCKS * CHOICES; Code below turn into various things, see MATLAB CODE STRUCTURE in oneNOTE GCC working notes

shockCount = 2;
choiceCount = 3;
stateCount = 4;

% 1. VALUE vector (STATES * SHOCKS * CHOICES by 1), this is generated by utility% evaluation function that takes as input STATES, SHOCKS, and CHOICES
valuesOri = sort(rand(choiceCount*shockCount*stateCount,1))

valuesOri = 24x1    
    0.0296
    0.1141
    0.1472
    0.1514
    0.1826
    0.1936
    0.2526
    0.2911
    0.3257
    0.3352

% 2. CHOICES by STATES * SHOCKS (ST1 SK1, ST1 SK2; ST2 SK1, etc), each% column are values for different choices given the same state and shock.
values = reshape(valuesOri,[choiceCount,shockCount*stateCount])

values = 3x8    
    0.0296    0.1514    0.2526    0.3352    0.5939    0.7065    0.8791    0.9204
    0.1141    0.1826    0.2911    0.3480    0.5992    0.7267    0.9001    0.9508
    0.1472    0.1936    0.3257    0.4578    0.6576    0.7792    0.9018    0.9658

% 3. SHOCKS by CHOICES * STATES (CH1 ST1, CH1 ST2; CH2 ST1, etc), each% column are two shocks for each state given the same choice. Note this% assumes that for different shocks of the same state choice vector is the% same.
values = reshape(values',[shockCount, choiceCount*stateCount])

values = 2x12    
    0.0296    0.2526    0.5939    0.8791    0.1141    0.2911    0.5992    0.9001    0.1472    0.3257    0.6576    0.9018
    0.1514    0.3352    0.7065    0.9204    0.1826    0.3480    0.7267    0.9508    0.1936    0.4578    0.7792    0.9658

% 4. AVG: 1 by CHOICES * STATES (CH1 ST1, CH1 ST2; CH2 ST1, etc), take% average over shocks for each state and choice combo
valuesMn = mean(values,1)

valuesMn = 1x12    
    0.0905    0.2939    0.6502    0.8997    0.1483    0.3196    0.6629    0.9254    0.1704    0.3918    0.7184    0.9338

% 5. AVG: CHOICES * STATES. From this matrix, one can now pick maximum% utility, and match that to the index on choice vector
valuesMn = reshape(valuesMn, [stateCount, choiceCount])'

valuesMn = 3x4    
    0.0905    0.2939    0.6502    0.8997
    0.1483    0.3196    0.6629    0.9254
    0.1704    0.3918    0.7184    0.9338

1.1.5.4 Pick Optimal Choice

choiceCount = 3;
stateCount = 4;

% 1. Matrix, each column is a state, each row is a choice
randMat = rand(choiceCount,stateCount)

randMat = 3x4    
    0.0733    0.5905    0.1731    0.1795
    0.0550    0.8539    0.1340    0.3175
    0.3232    0.2871    0.9947    0.5683

% 2. Maximum Value and Maximum Index
[maxVal maxIndex] = max(randMat)

maxVal = 1x4    
    0.3232    0.8539    0.9947    0.5683

maxIndex = 1x4    
     3     2     3     3

% 3. Linear index
linearIdx = maxIndex + ((1:stateCount)-1)*choiceCount

linearIdx = 1x4    
     3     5     9    12

% 4. Optimal Choices
randMat(linearIdx)

ans = 1x4    
    0.3232    0.8539    0.9947    0.5683

1.1.6 Accumarray Examples

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.6.1 Accumarry Basic Example

There are three unique values in ar_a, sum up the probabilities for each of the unique states. This is equivalent to sorting a matrix with a and prob, and computing sum for each.

ar_a = [3,2,1,3]';
ar_prob = [0.1,0.2,0.31,0.39]';
ar_sumprob = accumarray(ar_a, ar_prob);
tb_summed_prob = table(sort(unique(ar_a)), ar_sumprob);
disp(tb_summed_prob);

    Var1    ar_sumprob
    ____    __________

     1         0.31   
     2          0.2   
     3         0.49   

1.1.6.2 Accumarry For Discrete Random Variable

Upon solving a model, if we look for the mass at certain choices or states, accumarray could help aggregate up probabilities

a1 = [1,1,2,2]

a1 = 1x4    
     1     1     2     2

a2 = [3,2,1,3]

a2 = 1x4    
     3     2     1     3

a3 = [1,2,3,3]

a3 = 1x4    
     1     2     3     3


a = [a1;a2;a3]'/2

a = 4x3    
    0.5000    1.5000    0.5000
    0.5000    1.0000    1.0000
    1.0000    0.5000    1.5000
    1.0000    1.5000    1.5000


prob_a = zeros(size(a)) + 1/12

prob_a = 4x3    
    0.0833    0.0833    0.0833
    0.0833    0.0833    0.0833
    0.0833    0.0833    0.0833
    0.0833    0.0833    0.0833

[ar_idx_full, ~, ar_idx_of_unique] = unique(a)

ar_idx_full = 3x1    
    0.5000
    1.0000
    1.5000

ar_idx_of_unique = 12x1    
     1
     1
     2
     2
     3
     2
     1
     3
     1
     2

mt_idx_of_unique = reshape(ar_idx_of_unique, size(a))

mt_idx_of_unique = 4x3    
     1     3     1
     1     2     2
     2     1     3
     2     3     3


accumarray(mt_idx_of_unique(:,1), prob_a(:,1))

ans = 2x1    
    0.1667
    0.1667

accumarray(mt_idx_of_unique(:,2), prob_a(:,2))

ans = 3x1    
    0.0833
    0.0833
    0.1667

accumarray(mt_idx_of_unique(:,3), prob_a(:,3))

ans = 3x1    
    0.0833
    0.0833
    0.1667

1.1.7 Matlab Miscellaneous and Basic Numeric and Array Operations

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.1.7.1 Divisor, Quotient and Remainder

Given an array of integer values, and some divisor, find the quotient and remainder.

it_divisor = 10;
for bl_int=[0,1]
    if (bl_int == 1)
        ar_integers = int16([1,2,3, 11,12,13, 21,22,23]);
    else
        ar_integers = [1,2,3, 11,12,13, 21,22,23];
    end
    for it_integer=ar_integers
        % Modulus and quotient
        if(isinteger(it_integer))
            it_quotient = idivide(it_integer, it_divisor);
        else
            it_quotient = fix(it_integer/it_divisor);
        end
        it_remainder = rem(it_integer, it_divisor);

        if (it_remainder == 1)
            fl_power = 1.0;
        elseif (it_remainder == 2)
            fl_power = 1.5;
        elseif (it_remainder == 3)
            fl_power = 2.0;
        end

        if (it_quotient == 0)
            fl_base = 2;
        elseif (it_quotient == 1)
            fl_base = exp(1);
        elseif (it_quotient == 2)
            fl_base = 10;
        end

        fl_value = fl_base^fl_power;

        % Print
        st_print = strjoin(...
            ["Divide test:", ...
            ['bl_int=' num2str(bl_int)], ...
            ['it_integer=' num2str(it_integer)], ...
            ['it_remainder=' num2str(it_remainder)], ...
            ['it_quotient=' num2str(it_quotient)], ...
            ['fl_value=' num2str(fl_value)], ...
            ], ";");
        disp(st_print);

    end
end

Divide test:;bl_int=0;it_integer=1;it_remainder=1;it_quotient=0;fl_value=2
Divide test:;bl_int=0;it_integer=2;it_remainder=2;it_quotient=0;fl_value=2.8284
Divide test:;bl_int=0;it_integer=3;it_remainder=3;it_quotient=0;fl_value=4
Divide test:;bl_int=0;it_integer=11;it_remainder=1;it_quotient=1;fl_value=2.7183
Divide test:;bl_int=0;it_integer=12;it_remainder=2;it_quotient=1;fl_value=4.4817
Divide test:;bl_int=0;it_integer=13;it_remainder=3;it_quotient=1;fl_value=7.3891
Divide test:;bl_int=0;it_integer=21;it_remainder=1;it_quotient=2;fl_value=10
Divide test:;bl_int=0;it_integer=22;it_remainder=2;it_quotient=2;fl_value=31.6228
Divide test:;bl_int=0;it_integer=23;it_remainder=3;it_quotient=2;fl_value=100
Divide test:;bl_int=1;it_integer=1;it_remainder=1;it_quotient=0;fl_value=2
Divide test:;bl_int=1;it_integer=2;it_remainder=2;it_quotient=0;fl_value=2.8284
Divide test:;bl_int=1;it_integer=3;it_remainder=3;it_quotient=0;fl_value=4
Divide test:;bl_int=1;it_integer=11;it_remainder=1;it_quotient=1;fl_value=2.7183
Divide test:;bl_int=1;it_integer=12;it_remainder=2;it_quotient=1;fl_value=4.4817
Divide test:;bl_int=1;it_integer=13;it_remainder=3;it_quotient=1;fl_value=7.3891
Divide test:;bl_int=1;it_integer=21;it_remainder=1;it_quotient=2;fl_value=10
Divide test:;bl_int=1;it_integer=22;it_remainder=2;it_quotient=2;fl_value=31.6228
Divide test:;bl_int=1;it_integer=23;it_remainder=3;it_quotient=2;fl_value=100

1.1.7.2 Check if Array is All Above or Below Zero

There is an array that contains possible NaN values, check if all elements of array are positive, or all elements are negative, ignoring the NaN values.

for it_arrays=[1,2,3,4,5,6]
    if (it_arrays == 1)
        ar_values = [0.0001, 0.0002, 0.0005, 0.0012, 0.0013, NaN, NaN, NaN, NaN];
    elseif (it_arrays == 2)
        ar_values = [NaN, -0.0002, -0.0005, -0.0012, -0.0013, NaN, NaN, NaN, NaN];
    elseif (it_arrays == 3)
        ar_values = [0.0001, 0.0002, 0.0005, 0.0012, 0.0013];
    elseif (it_arrays == 4)
        ar_values = [-0.0002, -0.0005, -0.0012, -0.0013];
    elseif (it_arrays == 5)
        ar_values = [-0.0002, 0.0005, -0.0012, -0.0013];
    elseif (it_arrays == 6)
        ar_values = [-0.0002, 0.0005, -0.0012, NaN, -0.0013];
    end
    bl_all_pos = min(ar_values(~isnan(ar_values))>=0);
    bl_all_neg = min(ar_values(~isnan(ar_values))<=0);
    st_print = ['str=' num2str(it_arrays) ...
        ' has bl_all_pos=' num2str(bl_all_pos) ' and bl_all_neg=' num2str(bl_all_neg)];
    disp(st_print);
end

str=1 has bl_all_pos=1 and bl_all_neg=0
str=2 has bl_all_pos=0 and bl_all_neg=1
str=3 has bl_all_pos=1 and bl_all_neg=0
str=4 has bl_all_pos=0 and bl_all_neg=1
str=5 has bl_all_pos=0 and bl_all_neg=0
str=6 has bl_all_pos=0 and bl_all_neg=0

1.1.7.3 Check Parameter Types

There parameter input can either be a cell array or an integer, conditional processing based on parameter input type. To distinguish between an array or container map, for example, can use isnumeric or isfloat.

% Float and Cell
curEstiParamA = 1;
curEstiParamB = {146, 'R3'};
curEstiParamC = rand([1,5]);
curEstiParamD = [1,2,3,4.5];
curEstiParamE = containers.Map('KeyType','char', 'ValueType','any');
param_map('share_unbanked_j') = 12;
param_map('equi_r_j') = 2;
% test if is float
st_test = strjoin(...
    ["", ...
    ['isfloat(curEstiParamA)=' num2str(isfloat(curEstiParamA))], ...
    ['isfloat(curEstiParamB)=' num2str(isfloat(curEstiParamB))], ...
    ['isfloat(curEstiParamC)=' num2str(isfloat(curEstiParamC))], ...
    ['isfloat(curEstiParamD)=' num2str(isfloat(curEstiParamD))], ...
    ['isfloat(curEstiParamE)=' num2str(isfloat(curEstiParamE))], ...
    ], ";");
disp(st_test);

;isfloat(curEstiParamA)=1;isfloat(curEstiParamB)=0;isfloat(curEstiParamC)=1;isfloat(curEstiParamD)=1;isfloat(curEstiParamE)=0

% test if is cell
st_test = strjoin(...
    ["", ...
    ['iscell(curEstiParamA)=' num2str(iscell(curEstiParamA))], ...
    ['iscell(curEstiParamB)=' num2str(iscell(curEstiParamB))], ...
    ['iscell(curEstiParamC)=' num2str(iscell(curEstiParamC))], ...
    ['iscell(curEstiParamD)=' num2str(iscell(curEstiParamD))], ...
    ['iscell(curEstiParamE)=' num2str(iscell(curEstiParamE))], ...
    ], ";");
disp(st_test);

;iscell(curEstiParamA)=0;iscell(curEstiParamB)=1;iscell(curEstiParamC)=0;iscell(curEstiParamD)=0;iscell(curEstiParamE)=0

% test if is numeric
st_test = strjoin(...
    ["", ...
    ['isnumeric(curEstiParamA)=' num2str(isfloat(curEstiParamA))], ...
    ['isnumeric(curEstiParamB)=' num2str(isfloat(curEstiParamB))], ...
    ['isnumeric(curEstiParamC)=' num2str(isfloat(curEstiParamC))], ...
    ['isnumeric(curEstiParamD)=' num2str(isfloat(curEstiParamD))], ...
    ['isnumeric(curEstiParamE)=' num2str(isfloat(curEstiParamE))], ...
    ], ";");
disp(st_test);

;isnumeric(curEstiParamA)=1;isnumeric(curEstiParamB)=0;isnumeric(curEstiParamC)=1;isnumeric(curEstiParamD)=1;isnumeric(curEstiParamE)=0

1.1.7.4 Check if a value is an array of single scalar boolean

A function could take an array, if the array parameter input is boolean and false, then generate the array needed by the function in a different way. All that is needed is a NaN checker, works for scalar or array of NaN.

rng(123);
it_len = 3;
for it_case=[1,2,3]
    
    if (it_case == 1)        
        ob_val = rand(1,it_len);
    elseif (it_case == 2)
        % Single NaN
        ob_val = NaN;
    elseif (it_case == 3)
        % Single NaN
        ob_val = NaN(1,it_len);
    end
    
    if (~isnan(ob_val))
        % Input is the output vector since input is not NaN
        ob_val_out = ob_val;
    else
        % Generates random output vector since input is not provided
        ob_val_out = rand(1, it_len);
    end

    st_test = strjoin(...
        ["", ...
        ['ob_val=' num2str(ob_val)], ...
        ['ob_val_out=' num2str(ob_val_out)], ...
        ], ";");
    disp(st_test);    
end

;ob_val=0.69647     0.28614     0.22685;ob_val_out=0.69647     0.28614     0.22685
;ob_val=NaN;ob_val_out=0.55131     0.71947     0.42311
;ob_val=NaN  NaN  NaN;ob_val_out=0.98076     0.68483     0.48093

1.1.7.5 Compare Array Values That are Approximately Similar

What is the best way to compare floats for almost-equality in Python?

  • rel_tol is a relative tolerance, it is multiplied by the greater of the magnitudes of the two arguments; as the values get larger, so does the allowed difference between them while still considering them equal.

  • abs_tol is an absolute tolerance that is applied as-is in all cases. If the difference is less than either of those tolerances, the values are considered equal.

rel_tol=1e-09;
abs_tol=0.0;
if_is_close = @(a,b) (abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol));
disp(['1 and 1, if_is_close:' num2str(if_is_close(1,1))]);

1 and 1, if_is_close:1

disp(['1e-300 and 1e-301, if_is_close:' num2str(if_is_close(1e-300,1e-301))]);

1e-300 and 1e-301, if_is_close:0

disp(['1+1e-9 and 1+1e-10, if_is_close:' num2str(if_is_close(1+1e-9,1+1e-10))]);

1+1e-9 and 1+1e-10, if_is_close:1

1.1.7.6 Imaginary Number Examples

rng(123);

% Imaginary array
ar_img = rand([1,7]) + 1i*rand([1,7]);

% Regular Array
ar_real = rand([1,10]);

% Combine arrays
ar_full = [ar_real ar_img];
ar_full = ar_full(randperm(length(ar_full)));
disp(ar_full);

  Columns 1 through 6

   0.6344 + 0.0000i   0.1755 + 0.0000i   0.5316 + 0.0000i   0.2861 + 0.4809i   0.7380 + 0.0000i   0.1825 + 0.0000i

  Columns 7 through 12

   0.6965 + 0.6848i   0.2269 + 0.3921i   0.7245 + 0.0000i   0.8494 + 0.0000i   0.6110 + 0.0000i   0.4231 + 0.4386i

  Columns 13 through 17

   0.9808 + 0.0597i   0.5318 + 0.0000i   0.3980 + 0.0000i   0.5513 + 0.3432i   0.7195 + 0.7290i


% real index
disp(~imag(ar_full));

   1   1   1   0   1   1   0   0   1   1   1   0   0   1   1   0   0


% Get Real and not real Components
disp(ar_full(imag(ar_full) == 0));

    0.6344    0.1755    0.5316    0.7380    0.1825    0.7245    0.8494    0.6110    0.5318    0.3980

disp(ar_full(imag(ar_full) ~= 0));

  Columns 1 through 6

   0.2861 + 0.4809i   0.6965 + 0.6848i   0.2269 + 0.3921i   0.4231 + 0.4386i   0.9808 + 0.0597i   0.5513 + 0.3432i

  Column 7

   0.7195 + 0.7290i

1.2 ND Dimensional Arrays

1.2.1 Joint Arrays All Combinations and by Random Subset

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.2.1.1 Given Several Arrays, General all Possible Combinations

There are several parameters, might want to simulate at all possible combinations. In the example below, there are four parmeters, generate a table with all possible combinations of the four parameters.

%% A. Quadc linh refh and refsd parameter grids
[it_p1, it_p2, it_p3] = deal(4, 3, 3);
ar_p1 = linspace(-0.09, -0.02, it_p1);
ar_p2 =  linspace( 0.020, 0.100, it_p2);
ar_p3 =  linspace(-0.100, -0.020, it_p3);
ar_p4 =  [0.05];

%% B. Mesh Parameters together
% ndgrid mesh together
[mn_p1, ~] = ndgrid(ar_p1, ar_p2, ar_p3, ar_p4);
% combine
[ar_p1_idx, ar_p2_idx, ar_p3_idx, ar_p4_idx] = ind2sub(size(mn_p1), find(mn_p1));
% Index and values
ar_p1_flat = ar_p1(ar_p1_idx)';
ar_p2_flat = ar_p2(ar_p2_idx)';
ar_p3_flat = ar_p3(ar_p3_idx)';
ar_p4_flat = ar_p4(ar_p4_idx)';
mt_paramsmesh_long = [ar_p1_idx(:), ar_p1_flat(:), ...
    ar_p2_idx(:), ar_p2_flat(:), ...
    ar_p3_idx(:), ar_p3_flat(:), ...
    ar_p4_idx(:), ar_p4_flat(:)];
% Sort by a and z
mt_paramsmesh_long = sortrows(mt_paramsmesh_long, [1,3, 5]);

% C. Create Table
tb_paramsmesh_long = array2table(mt_paramsmesh_long);
cl_col_names_a = {'quadc_idx', 'quadc_val', ...
    'linh_idx', 'linh_val', ...
    'refh_idx', 'rehfh_val', ...
    'refsd_idx', 'rehfsd_val'};
tb_paramsmesh_long.Properties.VariableNames = cl_col_names_a;
% D. Display Table
disp(tb_paramsmesh_long);

    quadc_idx    quadc_val    linh_idx    linh_val    refh_idx    rehfh_val    refsd_idx    rehfsd_val
    _________    _________    ________    ________    ________    _________    _________    __________

        1            -0.09       1          0.02         1           -0.1          1           0.05   
        1            -0.09       1          0.02         2          -0.06          1           0.05   
        1            -0.09       1          0.02         3          -0.02          1           0.05   
        1            -0.09       2          0.06         1           -0.1          1           0.05   
        1            -0.09       2          0.06         2          -0.06          1           0.05   
        1            -0.09       2          0.06         3          -0.02          1           0.05   
        1            -0.09       3           0.1         1           -0.1          1           0.05   
        1            -0.09       3           0.1         2          -0.06          1           0.05   
        1            -0.09       3           0.1         3          -0.02          1           0.05   
        2        -0.066667       1          0.02         1           -0.1          1           0.05   
        2        -0.066667       1          0.02         2          -0.06          1           0.05   
        2        -0.066667       1          0.02         3          -0.02          1           0.05   
        2        -0.066667       2          0.06         1           -0.1          1           0.05   
        2        -0.066667       2          0.06         2          -0.06          1           0.05   
        2        -0.066667       2          0.06         3          -0.02          1           0.05   
        2        -0.066667       3           0.1         1           -0.1          1           0.05   
        2        -0.066667       3           0.1         2          -0.06          1           0.05   
        2        -0.066667       3           0.1         3          -0.02          1           0.05   
        3        -0.043333       1          0.02         1           -0.1          1           0.05   
        3        -0.043333       1          0.02         2          -0.06          1           0.05   
        3        -0.043333       1          0.02         3          -0.02          1           0.05   
        3        -0.043333       2          0.06         1           -0.1          1           0.05   
        3        -0.043333       2          0.06         2          -0.06          1           0.05   
        3        -0.043333       2          0.06         3          -0.02          1           0.05   
        3        -0.043333       3           0.1         1           -0.1          1           0.05   
        3        -0.043333       3           0.1         2          -0.06          1           0.05   
        3        -0.043333       3           0.1         3          -0.02          1           0.05   
        4            -0.02       1          0.02         1           -0.1          1           0.05   
        4            -0.02       1          0.02         2          -0.06          1           0.05   
        4            -0.02       1          0.02         3          -0.02          1           0.05   
        4            -0.02       2          0.06         1           -0.1          1           0.05   
        4            -0.02       2          0.06         2          -0.06          1           0.05   
        4            -0.02       2          0.06         3          -0.02          1           0.05   
        4            -0.02       3           0.1         1           -0.1          1           0.05   
        4            -0.02       3           0.1         2          -0.06          1           0.05   
        4            -0.02       3           0.1         3          -0.02          1           0.05   

1.2.1.2 Matlab Draw Random with and without Replacement

%Generate a matrix named foo, with limited numbers
rng(1234);
foo = unique((round((randn(5,1)+1)*100)));
disp(foo);

     5
    78
   154
   219
   232


% draw 10 random samples without replacement
index = randsample(1:length(foo), 4);
bar_rand_noreplace = foo(index,:);

% draw 1000 random samples with replacement
index = randsample(1:length(foo), 4, true);
bar_rand_replace = foo(index,:);

% Display
disp(table(bar_rand_noreplace, bar_rand_replace));

    bar_rand_noreplace    bar_rand_replace
    __________________    ________________

             5                   78       
            78                  154       
           154                  219       
           232                  219       

1.2.1.3 Matrix Meshgrid to Loop Permutated Vectors

Meshgrid to generate all permutations of arrays.

k = linspace(1,10,10);
kp = linspace(1,10,10);
z = linspace(0,1,10);
 
[kM kpM zM] = meshgrid(k,kp,z);
kMVec = kM(:);
kMpVec = kpM(:);
zMVec = zM(:);
 
outputVec = zeros(size(zMVec));
for a=1:length(zMVec)
     outputVec(a) = kMVec(a)+kMpVec(a)+zMVec(a);
end
 
outputTens = reshape(outputVec,size(kM));
disp(outputTens);

(:,:,1) =

     2     3     4     5     6     7     8     9    10    11
     3     4     5     6     7     8     9    10    11    12
     4     5     6     7     8     9    10    11    12    13
     5     6     7     8     9    10    11    12    13    14
     6     7     8     9    10    11    12    13    14    15
     7     8     9    10    11    12    13    14    15    16
     8     9    10    11    12    13    14    15    16    17
     9    10    11    12    13    14    15    16    17    18
    10    11    12    13    14    15    16    17    18    19
    11    12    13    14    15    16    17    18    19    20


(:,:,2) =

    2.1111    3.1111    4.1111    5.1111    6.1111    7.1111    8.1111    9.1111   10.1111   11.1111
    3.1111    4.1111    5.1111    6.1111    7.1111    8.1111    9.1111   10.1111   11.1111   12.1111
    4.1111    5.1111    6.1111    7.1111    8.1111    9.1111   10.1111   11.1111   12.1111   13.1111
    5.1111    6.1111    7.1111    8.1111    9.1111   10.1111   11.1111   12.1111   13.1111   14.1111
    6.1111    7.1111    8.1111    9.1111   10.1111   11.1111   12.1111   13.1111   14.1111   15.1111
    7.1111    8.1111    9.1111   10.1111   11.1111   12.1111   13.1111   14.1111   15.1111   16.1111
    8.1111    9.1111   10.1111   11.1111   12.1111   13.1111   14.1111   15.1111   16.1111   17.1111
    9.1111   10.1111   11.1111   12.1111   13.1111   14.1111   15.1111   16.1111   17.1111   18.1111
   10.1111   11.1111   12.1111   13.1111   14.1111   15.1111   16.1111   17.1111   18.1111   19.1111
   11.1111   12.1111   13.1111   14.1111   15.1111   16.1111   17.1111   18.1111   19.1111   20.1111


(:,:,3) =

    2.2222    3.2222    4.2222    5.2222    6.2222    7.2222    8.2222    9.2222   10.2222   11.2222
    3.2222    4.2222    5.2222    6.2222    7.2222    8.2222    9.2222   10.2222   11.2222   12.2222
    4.2222    5.2222    6.2222    7.2222    8.2222    9.2222   10.2222   11.2222   12.2222   13.2222
    5.2222    6.2222    7.2222    8.2222    9.2222   10.2222   11.2222   12.2222   13.2222   14.2222
    6.2222    7.2222    8.2222    9.2222   10.2222   11.2222   12.2222   13.2222   14.2222   15.2222
    7.2222    8.2222    9.2222   10.2222   11.2222   12.2222   13.2222   14.2222   15.2222   16.2222
    8.2222    9.2222   10.2222   11.2222   12.2222   13.2222   14.2222   15.2222   16.2222   17.2222
    9.2222   10.2222   11.2222   12.2222   13.2222   14.2222   15.2222   16.2222   17.2222   18.2222
   10.2222   11.2222   12.2222   13.2222   14.2222   15.2222   16.2222   17.2222   18.2222   19.2222
   11.2222   12.2222   13.2222   14.2222   15.2222   16.2222   17.2222   18.2222   19.2222   20.2222


(:,:,4) =

    2.3333    3.3333    4.3333    5.3333    6.3333    7.3333    8.3333    9.3333   10.3333   11.3333
    3.3333    4.3333    5.3333    6.3333    7.3333    8.3333    9.3333   10.3333   11.3333   12.3333
    4.3333    5.3333    6.3333    7.3333    8.3333    9.3333   10.3333   11.3333   12.3333   13.3333
    5.3333    6.3333    7.3333    8.3333    9.3333   10.3333   11.3333   12.3333   13.3333   14.3333
    6.3333    7.3333    8.3333    9.3333   10.3333   11.3333   12.3333   13.3333   14.3333   15.3333
    7.3333    8.3333    9.3333   10.3333   11.3333   12.3333   13.3333   14.3333   15.3333   16.3333
    8.3333    9.3333   10.3333   11.3333   12.3333   13.3333   14.3333   15.3333   16.3333   17.3333
    9.3333   10.3333   11.3333   12.3333   13.3333   14.3333   15.3333   16.3333   17.3333   18.3333
   10.3333   11.3333   12.3333   13.3333   14.3333   15.3333   16.3333   17.3333   18.3333   19.3333
   11.3333   12.3333   13.3333   14.3333   15.3333   16.3333   17.3333   18.3333   19.3333   20.3333


(:,:,5) =

    2.4444    3.4444    4.4444    5.4444    6.4444    7.4444    8.4444    9.4444   10.4444   11.4444
    3.4444    4.4444    5.4444    6.4444    7.4444    8.4444    9.4444   10.4444   11.4444   12.4444
    4.4444    5.4444    6.4444    7.4444    8.4444    9.4444   10.4444   11.4444   12.4444   13.4444
    5.4444    6.4444    7.4444    8.4444    9.4444   10.4444   11.4444   12.4444   13.4444   14.4444
    6.4444    7.4444    8.4444    9.4444   10.4444   11.4444   12.4444   13.4444   14.4444   15.4444
    7.4444    8.4444    9.4444   10.4444   11.4444   12.4444   13.4444   14.4444   15.4444   16.4444
    8.4444    9.4444   10.4444   11.4444   12.4444   13.4444   14.4444   15.4444   16.4444   17.4444
    9.4444   10.4444   11.4444   12.4444   13.4444   14.4444   15.4444   16.4444   17.4444   18.4444
   10.4444   11.4444   12.4444   13.4444   14.4444   15.4444   16.4444   17.4444   18.4444   19.4444
   11.4444   12.4444   13.4444   14.4444   15.4444   16.4444   17.4444   18.4444   19.4444   20.4444


(:,:,6) =

    2.5556    3.5556    4.5556    5.5556    6.5556    7.5556    8.5556    9.5556   10.5556   11.5556
    3.5556    4.5556    5.5556    6.5556    7.5556    8.5556    9.5556   10.5556   11.5556   12.5556
    4.5556    5.5556    6.5556    7.5556    8.5556    9.5556   10.5556   11.5556   12.5556   13.5556
    5.5556    6.5556    7.5556    8.5556    9.5556   10.5556   11.5556   12.5556   13.5556   14.5556
    6.5556    7.5556    8.5556    9.5556   10.5556   11.5556   12.5556   13.5556   14.5556   15.5556
    7.5556    8.5556    9.5556   10.5556   11.5556   12.5556   13.5556   14.5556   15.5556   16.5556
    8.5556    9.5556   10.5556   11.5556   12.5556   13.5556   14.5556   15.5556   16.5556   17.5556
    9.5556   10.5556   11.5556   12.5556   13.5556   14.5556   15.5556   16.5556   17.5556   18.5556
   10.5556   11.5556   12.5556   13.5556   14.5556   15.5556   16.5556   17.5556   18.5556   19.5556
   11.5556   12.5556   13.5556   14.5556   15.5556   16.5556   17.5556   18.5556   19.5556   20.5556


(:,:,7) =

    2.6667    3.6667    4.6667    5.6667    6.6667    7.6667    8.6667    9.6667   10.6667   11.6667
    3.6667    4.6667    5.6667    6.6667    7.6667    8.6667    9.6667   10.6667   11.6667   12.6667
    4.6667    5.6667    6.6667    7.6667    8.6667    9.6667   10.6667   11.6667   12.6667   13.6667
    5.6667    6.6667    7.6667    8.6667    9.6667   10.6667   11.6667   12.6667   13.6667   14.6667
    6.6667    7.6667    8.6667    9.6667   10.6667   11.6667   12.6667   13.6667   14.6667   15.6667
    7.6667    8.6667    9.6667   10.6667   11.6667   12.6667   13.6667   14.6667   15.6667   16.6667
    8.6667    9.6667   10.6667   11.6667   12.6667   13.6667   14.6667   15.6667   16.6667   17.6667
    9.6667   10.6667   11.6667   12.6667   13.6667   14.6667   15.6667   16.6667   17.6667   18.6667
   10.6667   11.6667   12.6667   13.6667   14.6667   15.6667   16.6667   17.6667   18.6667   19.6667
   11.6667   12.6667   13.6667   14.6667   15.6667   16.6667   17.6667   18.6667   19.6667   20.6667


(:,:,8) =

    2.7778    3.7778    4.7778    5.7778    6.7778    7.7778    8.7778    9.7778   10.7778   11.7778
    3.7778    4.7778    5.7778    6.7778    7.7778    8.7778    9.7778   10.7778   11.7778   12.7778
    4.7778    5.7778    6.7778    7.7778    8.7778    9.7778   10.7778   11.7778   12.7778   13.7778
    5.7778    6.7778    7.7778    8.7778    9.7778   10.7778   11.7778   12.7778   13.7778   14.7778
    6.7778    7.7778    8.7778    9.7778   10.7778   11.7778   12.7778   13.7778   14.7778   15.7778
    7.7778    8.7778    9.7778   10.7778   11.7778   12.7778   13.7778   14.7778   15.7778   16.7778
    8.7778    9.7778   10.7778   11.7778   12.7778   13.7778   14.7778   15.7778   16.7778   17.7778
    9.7778   10.7778   11.7778   12.7778   13.7778   14.7778   15.7778   16.7778   17.7778   18.7778
   10.7778   11.7778   12.7778   13.7778   14.7778   15.7778   16.7778   17.7778   18.7778   19.7778
   11.7778   12.7778   13.7778   14.7778   15.7778   16.7778   17.7778   18.7778   19.7778   20.7778


(:,:,9) =

    2.8889    3.8889    4.8889    5.8889    6.8889    7.8889    8.8889    9.8889   10.8889   11.8889
    3.8889    4.8889    5.8889    6.8889    7.8889    8.8889    9.8889   10.8889   11.8889   12.8889
    4.8889    5.8889    6.8889    7.8889    8.8889    9.8889   10.8889   11.8889   12.8889   13.8889
    5.8889    6.8889    7.8889    8.8889    9.8889   10.8889   11.8889   12.8889   13.8889   14.8889
    6.8889    7.8889    8.8889    9.8889   10.8889   11.8889   12.8889   13.8889   14.8889   15.8889
    7.8889    8.8889    9.8889   10.8889   11.8889   12.8889   13.8889   14.8889   15.8889   16.8889
    8.8889    9.8889   10.8889   11.8889   12.8889   13.8889   14.8889   15.8889   16.8889   17.8889
    9.8889   10.8889   11.8889   12.8889   13.8889   14.8889   15.8889   16.8889   17.8889   18.8889
   10.8889   11.8889   12.8889   13.8889   14.8889   15.8889   16.8889   17.8889   18.8889   19.8889
   11.8889   12.8889   13.8889   14.8889   15.8889   16.8889   17.8889   18.8889   19.8889   20.8889


(:,:,10) =

     3     4     5     6     7     8     9    10    11    12
     4     5     6     7     8     9    10    11    12    13
     5     6     7     8     9    10    11    12    13    14
     6     7     8     9    10    11    12    13    14    15
     7     8     9    10    11    12    13    14    15    16
     8     9    10    11    12    13    14    15    16    17
     9    10    11    12    13    14    15    16    17    18
    10    11    12    13    14    15    16    17    18    19
    11    12    13    14    15    16    17    18    19    20
    12    13    14    15    16    17    18    19    20    21

1.2.1.4 Given Integer Arrays, All Possible Combinations

given any sizes arrays, N of them, create all possible combinations

ar_it_a = 1:3;
ar_it_b = 1:2;
ar_it_c = 2:4;
ar_it_d = -1:-1:-2;
ar_it_e = 0.1;

cl_ar_all = {ar_it_a, ar_it_b, ar_it_c, ar_it_d, ar_it_e};
cl_mt_all = cl_ar_all;
[cl_mt_all{:}] = ndgrid(cl_ar_all{:});
mt_it_allcombo = cell2mat(cellfun(@(m) m(:), cl_mt_all, 'uni', 0));

disp(mt_it_allcombo)

    1.0000    1.0000    2.0000   -1.0000    0.1000
    2.0000    1.0000    2.0000   -1.0000    0.1000
    3.0000    1.0000    2.0000   -1.0000    0.1000
    1.0000    2.0000    2.0000   -1.0000    0.1000
    2.0000    2.0000    2.0000   -1.0000    0.1000
    3.0000    2.0000    2.0000   -1.0000    0.1000
    1.0000    1.0000    3.0000   -1.0000    0.1000
    2.0000    1.0000    3.0000   -1.0000    0.1000
    3.0000    1.0000    3.0000   -1.0000    0.1000
    1.0000    2.0000    3.0000   -1.0000    0.1000
    2.0000    2.0000    3.0000   -1.0000    0.1000
    3.0000    2.0000    3.0000   -1.0000    0.1000
    1.0000    1.0000    4.0000   -1.0000    0.1000
    2.0000    1.0000    4.0000   -1.0000    0.1000
    3.0000    1.0000    4.0000   -1.0000    0.1000
    1.0000    2.0000    4.0000   -1.0000    0.1000
    2.0000    2.0000    4.0000   -1.0000    0.1000
    3.0000    2.0000    4.0000   -1.0000    0.1000
    1.0000    1.0000    2.0000   -2.0000    0.1000
    2.0000    1.0000    2.0000   -2.0000    0.1000
    3.0000    1.0000    2.0000   -2.0000    0.1000
    1.0000    2.0000    2.0000   -2.0000    0.1000
    2.0000    2.0000    2.0000   -2.0000    0.1000
    3.0000    2.0000    2.0000   -2.0000    0.1000
    1.0000    1.0000    3.0000   -2.0000    0.1000
    2.0000    1.0000    3.0000   -2.0000    0.1000
    3.0000    1.0000    3.0000   -2.0000    0.1000
    1.0000    2.0000    3.0000   -2.0000    0.1000
    2.0000    2.0000    3.0000   -2.0000    0.1000
    3.0000    2.0000    3.0000   -2.0000    0.1000
    1.0000    1.0000    4.0000   -2.0000    0.1000
    2.0000    1.0000    4.0000   -2.0000    0.1000
    3.0000    1.0000    4.0000   -2.0000    0.1000
    1.0000    2.0000    4.0000   -2.0000    0.1000
    2.0000    2.0000    4.0000   -2.0000    0.1000
    3.0000    2.0000    4.0000   -2.0000    0.1000

1.2.2 3D, 4D, ND Arrays Reshape and Rearrange Dimensions

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.2.2.1 3D Array to Cell Array of Matrix Split by Last Dimension

Convert Multi-dimensional arrays to a cell array consistent of two dimensional arrays. In this example, we split by the 3rd dimension, so the number of output matrixes is equal to the length of the 3rd dimension.

First create a three dimensional array, two matrixes that are 4 by 3 each:

% Create a 3D Array
rng(123);
mn_rand = rand(4,3,2);
disp(mn_rand);

(:,:,1) =

    0.6965    0.7195    0.4809
    0.2861    0.4231    0.3921
    0.2269    0.9808    0.3432
    0.5513    0.6848    0.7290


(:,:,2) =

    0.4386    0.1825    0.6344
    0.0597    0.1755    0.8494
    0.3980    0.5316    0.7245
    0.7380    0.5318    0.6110

Now convert the 3 dimensional array to a 2 by 1 cell array that contains matrixes in each cell:

% Squeece 3D array to a Cell array of matrixes
cl_mn_rand = squeeze(num2cell(mn_rand, [1,2]));
celldisp(cl_mn_rand);


cl_mn_rand{1} =
 
    0.6965    0.7195    0.4809
    0.2861    0.4231    0.3921
    0.2269    0.9808    0.3432
    0.5513    0.6848    0.7290



cl_mn_rand{2} =
 
    0.4386    0.1825    0.6344
    0.0597    0.1755    0.8494
    0.3980    0.5316    0.7245
    0.7380    0.5318    0.6110

1.2.2.2 4D Array to Cell Array of Matrix Split by Last Two Dimensions

Convert 4D Multi-dimensional arrays to a cell array consistent of two dimensional arrays. In this example, the first two dimensions determine the resulting matrix size, the the 3rd and the 4th dimensions are categorical.

First create a four dimensional array, four matrixes stored each matrix is 2 by 2:

% Create a 3D Array
rng(123);
mn_rand = rand(2,2,2,2);
disp(mn_rand);

(:,:,1,1) =

    0.6965    0.2269
    0.2861    0.5513


(:,:,2,1) =

    0.7195    0.9808
    0.4231    0.6848


(:,:,1,2) =

    0.4809    0.3432
    0.3921    0.7290


(:,:,2,2) =

    0.4386    0.3980
    0.0597    0.7380

Now convert the 4 dimensional array to a 2 by 2 cell array that contains matrixes in each cell:

% Squeece 3D array to a Cell array of matrixes
cl_mn_rand = squeeze(num2cell(mn_rand, [1,2]));
celldisp(cl_mn_rand);


cl_mn_rand{1,1} =
 
    0.6965    0.2269
    0.2861    0.5513



cl_mn_rand{2,1} =
 
    0.7195    0.9808
    0.4231    0.6848



cl_mn_rand{1,2} =
 
    0.4809    0.3432
    0.3921    0.7290



cl_mn_rand{2,2} =
 
    0.4386    0.3980
    0.0597    0.7380

1.2.2.3 4D Array to Cell Array of Matrix Split by First and Fourth Dimensions Rearrange Dimensions

Suppose we store policy and value function given four state variables. The first one is age, the second one is asset, the third one is shock, and the fourth one is the number of kids. We start out with a four dimensional matrix. The objective is to create a two dimensional cell array as output where indexed by the 1st and 4th dimension of the underlying numeric array, and the elements of the 2D cell array are matrixes.

This is achieved by the permute function. We first rearrange the matrix, so that the 2nd and 3rd dimensions become the 1st and 2nd, then we use the technique used above to squeeze out the first two dimensions as matrixes with the last two as categories.

First, generate the 2 by 2 by 2 by 2, (Age, A, Z, Kids Count), matrix:

% Create a 3D Array
rng(123);
% (Age, A, Z, Kids Count)
mn_rand = rand(2,2,2,2);

Second, loop out the (A,Z) matrix by Age and Kids Count, this shows us what we want to achieve. Note that each row is Age, each column is A, each submatrix is z, and each super-matrix is kid-count. So from slicing, each column printed out are different value of A, the two submatrixes printed out are for each z. For the output structure where we want a (A,Z) matrix, the columns need to become rows, and the submatrix need to become columns.

% Show Matrix by Age and Kids
for it_age = 1:size(mn_rand,1)
    for it_kids = 1:size(mn_rand,4)
        disp(strcat(['it_age:' num2str(it_age) ', it_kids:' num2str(it_kids)]))
        disp(mn_rand(it_age,:,:,it_kids));
    end
end

it_age:1, it_kids:1
(:,:,1) =

    0.6965    0.2269


(:,:,2) =

    0.7195    0.9808
it_age:1, it_kids:2
(:,:,1) =

    0.4809    0.3432


(:,:,2) =

    0.4386    0.3980
it_age:2, it_kids:1
(:,:,1) =

    0.2861    0.5513


(:,:,2) =

    0.4231    0.6848
it_age:2, it_kids:2
(:,:,1) =

    0.3921    0.7290


(:,:,2) =

    0.0597    0.7380

Third, we permutate the matrix and squeeze to arrive at the 2 by 2 cell, note that step two is just to show via loop what we should get:

% Rearrange dimensions
mn_rand_2314 = permute(mn_rand, [2,3,1,4]);
% Squeeze the first two dimensiosn as before
cl_mn_rand = squeeze(num2cell(mn_rand_2314, [1,2]));
% show
celldisp(cl_mn_rand);


cl_mn_rand{1,1} =
 
    0.6965    0.7195
    0.2269    0.9808



cl_mn_rand{2,1} =
 
    0.2861    0.4231
    0.5513    0.6848



cl_mn_rand{1,2} =
 
    0.4809    0.4386
    0.3432    0.3980



cl_mn_rand{2,2} =
 
    0.3921    0.0597
    0.7290    0.7380

1.2.2.4 ND Array Summarize in Table

Given an ND dataframe, summarize the first two dimensions. For each possible combination of the 3rd and 4th dimension, generate mean, sd, min and max over the matrix of the first two dimensions. This is similar to a tabulation function.

First, we generate several array of information:

% Initialize and Squeeze
rng(123);
mn_rand = rand(2,2,2,2);
cln_mt_rand = squeeze(num2cell(mn_rand, [1,2]));
cl_mt_rand = cln_mt_rand(:);
celldisp(cl_mt_rand);


cl_mt_rand{1} =
 
    0.6965    0.2269
    0.2861    0.5513



cl_mt_rand{2} =
 
    0.7195    0.9808
    0.4231    0.6848



cl_mt_rand{3} =
 
    0.4809    0.3432
    0.3921    0.7290



cl_mt_rand{4} =
 
    0.4386    0.3980
    0.0597    0.7380

Second, create two arrays that tracks for each element of cl_mt_rand, which one of the 3rd and 4th dimensions they correspond to:

ar_dim_3 = [31,32]';
ar_dim_4 = [41,42]';
[mt_dim_3, mt_dim_4] = ndgrid(ar_dim_3, ar_dim_4);
ar_dim_3 = mt_dim_3(:);
ar_dim_4 = mt_dim_4(:);

Third, summarize each matrix:

% Over of matrix and summarize
ar_mean = zeros(size(cl_mt_rand));
ar_std = zeros(size(cl_mt_rand));
for it_mt=1:length(cl_mt_rand)
    mt_cur = cl_mt_rand{it_mt};
    ar_mean(it_mt) = mean(mt_cur, 'all');
    ar_std(it_mt) = std(mt_cur, [], 'all');
end

Fourth Construct a Table

% Constructe Table
tb_rowcols_tab = array2table([(1:length(cl_mt_rand))', ...
    ar_dim_3, ar_dim_4, ar_mean, ar_std]);
tb_rowcols_tab.Properties.VariableNames = ...
    matlab.lang.makeValidName(["i", "dim3", "dim4",  "mean", "std"]);
disp(tb_rowcols_tab);

    i    dim3    dim4     mean        std  
    _    ____    ____    _______    _______

    1     31      41     0.44019    0.22156
    2     32      41     0.70204     0.2281
    3     31      42     0.48632    0.17157
    4     32      42     0.40857    0.27764

1.2.2.5 ND Array Two-Way Summarize in Table

Given dataframe as above, but we now want to add to the resulting summary table additional columns, rather than taking the means of the entire matrix in the first two dimensions, we only take average with respect to the rows, the first dimension, the second dimension show up as coumn statistics names, still multiple stats. The results worked out here are embedded in the fx_summ_nd_array function of the MEconTools Package.

First, we generate several array of information:

% dimension names
st_title = 'Summarize values over a conditional on z (columns) and kids and marriage (rows)';
st_dim_1 = 'a';
st_dim_2 = 'z';
st_dim_3 = 'kid';
st_dim_4 = 'marriage';
% 3rd and fourth dimension values
ar_dim_2 = [-3, -1, 1, 3];
ar_dim_3 = [1,2,3];
ar_dim_4 = [0,1];
% Initialize and Squeeze
rng(123);
mn_rand = rand(10,4,3,2);
cln_mt_rand = squeeze(num2cell(mn_rand, [1,2]));
cl_mt_rand = cln_mt_rand(:);

Second, create two arrays that tracks for each element of cl_mt_rand, which one of the 3rd and 4th dimensions they correspond to:

[mt_dim_3, mt_dim_4] = ndgrid(ar_dim_3', ar_dim_4');
ar_dim_3 = mt_dim_3(:);
ar_dim_4 = mt_dim_4(:);

Third, summarize each matrix:

% Over of matrix and summarize
mt_mean = zeros(length(cl_mt_rand), size(mn_rand,2));
mt_std = zeros(length(cl_mt_rand), size(mn_rand,2));
for it_mt=1:length(cl_mt_rand)
    mt_cur = cl_mt_rand{it_mt};
    mt_mean(it_mt,:) = mean(mt_cur, 1);
    mt_std(it_mt,:) = std(mt_cur, [], 1);
end

Fourth Construct a Table

% Constructe Table
tb_rowcols_tab = array2table([(1:length(cl_mt_rand))', ...
    ar_dim_3, ar_dim_4, mt_mean, mt_std]);
% Column Names
cl_col_names_cate_dims = [string(st_dim_3), string(st_dim_4)];
cl_col_names_mn = strcat('mean_', st_dim_2, string(ar_dim_2));
cl_col_names_sd = strcat('sd_', st_dim_2, string(ar_dim_2));
tb_rowcols_tab.Properties.VariableNames = ...
    matlab.lang.makeValidName(["group", cl_col_names_cate_dims, cl_col_names_mn, cl_col_names_sd]);
% disp(['xxx ' st_title ' xxxxxxxxxxxxxxxxxxxxxxxxxxx']);
disp(tb_rowcols_tab);

    group    kid    marriage    mean_z_3    mean_z_1    mean_z1    mean_z3    sd_z_3     sd_z_1      sd_z1      sd_z3 
    _____    ___    ________    ________    ________    _______    _______    _______    _______    _______    _______

      1       1        0         0.5442     0.41278     0.53795    0.49542    0.22935    0.22945    0.21653    0.25245
      2       2        0        0.51894     0.52262     0.52544    0.45066    0.26787    0.23615    0.25833    0.31178
      3       3        0        0.48248      0.5238     0.50392    0.46534    0.27009    0.26676    0.26644    0.29449
      4       1        1        0.58343     0.50529     0.54361     0.5006    0.29578    0.30182    0.30952    0.27317
      5       2        1        0.58408     0.45941     0.50466    0.40081    0.25026    0.34704    0.31039    0.28693
      6       3        1        0.51148     0.49531     0.48963    0.47698     0.3271    0.24336    0.34498    0.34004

1.2.3 Multidimensional ND Array to 2D Matrix with Wide to Long

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.2.3.1 2D Matrix Wide to Long

There is a 2D matrix, the rows and columns are state variables (savings levels and shocks) for storage and graphing purposes, convert the 2D matrix where each row is a savings level and each column is a shock level to a 2D table where the first column records savings state, second column the level of shocks, and the third column stores the optimal policy or value at that particular combination of savings level and shock level.

First, generate a random 2D matrix:

% Create a 3D Array
it_z_n = 3;
it_a_n = 5;
% shock savings and shock array
ar_a = linspace(0.1, 50, it_a_n);
ar_z = linspace(-3, 3, it_z_n);
% function of a and z
mt_f_a_z = ar_a' + exp(ar_z);
% Display
disp(mt_f_a_z);

    0.1498    1.1000   20.1855
   12.6248   13.5750   32.6605
   25.0998   26.0500   45.1355
   37.5748   38.5250   57.6105
   50.0498   51.0000   70.0855

Second, from linear index to row and column index:

% Row and Column index for each matrix value
% Only keep non-NAN values
ar_id_isnan = isnan(mt_f_a_z);
[ar_a_idx, ar_z_idx] = ind2sub(size(mt_f_a_z), find(~ar_id_isnan));
% Display
disp([ar_a_idx, ar_a(ar_a_idx)', ar_z_idx, ar_z(ar_z_idx)']);

    1.0000    0.1000    1.0000   -3.0000
    2.0000   12.5750    1.0000   -3.0000
    3.0000   25.0500    1.0000   -3.0000
    4.0000   37.5250    1.0000   -3.0000
    5.0000   50.0000    1.0000   -3.0000
    1.0000    0.1000    2.0000         0
    2.0000   12.5750    2.0000         0
    3.0000   25.0500    2.0000         0
    4.0000   37.5250    2.0000         0
    5.0000   50.0000    2.0000         0
    1.0000    0.1000    3.0000    3.0000
    2.0000   12.5750    3.0000    3.0000
    3.0000   25.0500    3.0000    3.0000
    4.0000   37.5250    3.0000    3.0000
    5.0000   50.0000    3.0000    3.0000

Third, generate a 2d matrix in "table" format:

% Index and values
mt_policy_long = [ar_a_idx, ar_a(ar_a_idx)', ar_z_idx, ar_z(ar_z_idx)', mt_f_a_z(~ar_id_isnan)];
% Sort by a and z
mt_policy_long = sortrows(mt_policy_long, [1,3]);

Fourth, generate a Table with Column names:

% Create Table
tb_policy_long = array2table(mt_policy_long);
cl_col_names_a = {'a_idx', 'a_val', 'z_idx', 'z_val', 'pol_at_a_z'};
tb_policy_long.Properties.VariableNames = cl_col_names_a;
disp(tb_policy_long);

    a_idx    a_val     z_idx    z_val    pol_at_a_z
    _____    ______    _____    _____    __________

      1         0.1      1       -3       0.14979  
      1         0.1      2        0           1.1  
      1         0.1      3        3        20.186  
      2      12.575      1       -3        12.625  
      2      12.575      2        0        13.575  
      2      12.575      3        3        32.661  
      3       25.05      1       -3          25.1  
      3       25.05      2        0         26.05  
      3       25.05      3        3        45.136  
      4      37.525      1       -3        37.575  
      4      37.525      2        0        38.525  
      4      37.525      3        3        57.611  
      5          50      1       -3         50.05  
      5          50      2        0            51  
      5          50      3        3        70.086  

1.2.3.2 A Multidimensional ND Array with Many NaN Values

Continue with the previous exercise, but now we have more than 2 state variables.

Create a multidimensional Array with Many NaN Values. For example, we could have a dynamic lifecycle model with three endogenous varaibles, years of education accumulated, years of experiencesin blue and white collar jobs. By age 22, after starting to work at age 16, there are different possible combinations of G (schooling), X1 (white-collar), and X2 (blue-collar) jobs. These are exclusive choices in each year, so at age 16, assume that G = 0, X1 = 0 and X2 = 0. At age 16, they can choose to stay at home, school, or X1, or X2, exclusively. G, X1, X2 accumulate over time.

For each age, we can create multi-dimensional arrays with equal dimension for G, X1 and X2, to record consumption, value, etc at each element of the possible state-space. However, that matrix could have a lot of empty values.

In the example below, also has a X3 (military category).

% random number
rng(123);

% Max age means number of
MAX_YRS_POST16 = 3;

% store all
cl_EV = cell(MAX_YRS_POST16,1);

% Loop 1, solve BACKWARD
for it_yrs_post16=MAX_YRS_POST16:-1:1
    
    % Store some results, the matrix below includes all possible
    % state-space elements
    mn_ev_at_gx123 = NaN(it_yrs_post16, it_yrs_post16, it_yrs_post16, it_yrs_post16);
    
    % Loops 2, possibles Years attained so far as well as experiences
    for G=0:1:(it_yrs_post16-1)
        for X1=0:1:(it_yrs_post16-1-G)
            for X2=0:1:(it_yrs_post16-1-G-X1)
                for X3=0:1:(it_yrs_post16-1-G-X1-X2)
                    
                    % Double checkAre these combinations feasible?
                    if (G+X1+X2+X3 <= it_yrs_post16)
                        % just plug in a random number
                        mn_ev_at_gx123(G+1, X1+1, X2+1, X3+1) = rand();
                    end
                end
            end
        end
    end
    
    % store matrixes
    cl_EV{it_yrs_post16} = mn_ev_at_gx123;
    
end

% Display Results
celldisp(cl_EV);


cl_EV{1} =
 
    0.6344



cl_EV{2} =
 

(:,:,1,1) =

    0.7380    0.5316
    0.5318       NaN


(:,:,2,1) =

    0.1755       NaN
       NaN       NaN


(:,:,1,2) =

    0.1825       NaN
       NaN       NaN


(:,:,2,2) =

   NaN   NaN
   NaN   NaN



cl_EV{3} =
 

(:,:,1,1) =

    0.6965    0.9808    0.3921
    0.3432    0.0597       NaN
    0.3980       NaN       NaN


(:,:,2,1) =

    0.5513    0.4809       NaN
    0.4386       NaN       NaN
       NaN       NaN       NaN


(:,:,3,1) =

    0.4231       NaN       NaN
       NaN       NaN       NaN
       NaN       NaN       NaN


(:,:,1,2) =

    0.2861    0.6848       NaN
    0.7290       NaN       NaN
       NaN       NaN       NaN


(:,:,2,2) =

    0.7195       NaN       NaN
       NaN       NaN       NaN
       NaN       NaN       NaN


(:,:,3,2) =

   NaN   NaN   NaN
   NaN   NaN   NaN
   NaN   NaN   NaN


(:,:,1,3) =

    0.2269       NaN       NaN
       NaN       NaN       NaN
       NaN       NaN       NaN


(:,:,2,3) =

   NaN   NaN   NaN
   NaN   NaN   NaN
   NaN   NaN   NaN


(:,:,3,3) =

   NaN   NaN   NaN
   NaN   NaN   NaN
   NaN   NaN   NaN

1.2.3.3 Generate a Two Dimensional Matrix Based on ND Array for Only non-NaN Cell Values

We can generate a 2-dimensional matrix, what we can consider as a Table, with the information stored in the structures earlier. In this example, we can drop the NaN values. This matrix will be much larger in size due to explicitly storing X1, X2, X3 and G values then the ND array when most values are not NaN. But this output matrix can be much more easily interpretable and readable. When there are many many NaNs in the ND array, this matrix could be much smaller in size.

First, convert each element of the cell array above to a 2D matrix (with the same number of columns), then stack resulting matrixes together to form one big table.

% Create a 2D Array
for it_yrs_post16=MAX_YRS_POST16:-1:1
    % Get matrix at cell element
    mn_ev_at_gx123 = cl_EV{it_yrs_post16};
    % flaten multi-dimensional matrix
    ar_ev_at_gx123_flat = mn_ev_at_gx123(:);
    % find nan values
    ar_id_isnan = isnan(ar_ev_at_gx123_flat);
    % obtain dimension-specific index for nan positions
    [id_G, id_X1, id_X2, id_X3] = ind2sub(size(mn_ev_at_gx123), find(~ar_id_isnan));
    % generate 2-dimensional matrix (table)
    mt_ev_at_gx123 = [it_yrs_post16 + zeros(size(id_G)), ...
        (id_G-1), (id_X1-1), (id_X2-1), (id_X3-1), ...
        ar_ev_at_gx123_flat(~ar_id_isnan)];
    % stack results
    if (it_yrs_post16 == MAX_YRS_POST16)
        mt_ev_at_gx123_all = mt_ev_at_gx123;
    else
        mt_ev_at_gx123_all = [mt_ev_at_gx123_all; mt_ev_at_gx123];
    end
end
% Sort
mt_ev_at_gx123_all = sortrows(mt_ev_at_gx123_all, [1,2,3,4]);
% Create Table
tb_ev_at_gx123_all = array2table(mt_ev_at_gx123_all);
cl_col_names_a = {'YRS_POST16', 'G', 'X1', 'X2', 'X3', 'EV'};
tb_ev_at_gx123_all.Properties.VariableNames = cl_col_names_a;
disp(tb_ev_at_gx123_all);

    YRS_POST16    G    X1    X2    X3       EV   
    __________    _    __    __    __    ________

        1         0    0     0     0       0.6344
        2         0    0     0     0        0.738
        2         0    0     0     1      0.18249
        2         0    0     1     0      0.17545
        2         0    1     0     0      0.53155
        2         1    0     0     0      0.53183
        3         0    0     0     0      0.69647
        3         0    0     0     1      0.28614
        3         0    0     0     2      0.22685
        3         0    0     1     0      0.55131
        3         0    0     1     1      0.71947
        3         0    0     2     0      0.42311
        3         0    1     0     0      0.98076
        3         0    1     0     1      0.68483
        3         0    1     1     0      0.48093
        3         0    2     0     0      0.39212
        3         1    0     0     0      0.34318
        3         1    0     0     1      0.72905
        3         1    0     1     0      0.43857
        3         1    1     0     0     0.059678
        3         2    0     0     0      0.39804

1.2.3.4 Mesh Three Vectors Together then Generate A Flat Table

There are three parameters, quadratic of preference, height preference, and reference points preference. Mesh three vectors together with ndgrid. Then generate a flat table with the index of the parameters as well as the values of the parameters.

% Generate Arrays
[it_quadc, it_linh, it_refh] = deal(2, 2, 2);
ar_fl_quadc = linspace(-0.01, -0.001, it_quadc);
ar_fl_linh = linspace(0.01, 0.05, it_linh);
ar_fl_refh = linspace(-0.01, -0.05, it_refh);
% ndgrid mesh together
[mn_fl_quadc, ~] = ndgrid(ar_fl_quadc, ar_fl_linh, ar_fl_refh);
% combine
[ar_it_quadc_idx, ar_it_linh_idx, ar_it_refh_idx] = ind2sub(size(mn_fl_quadc), find(mn_fl_quadc));
% Index and values
mt_paramsmesh_long = [ar_it_quadc_idx, ar_fl_quadc(ar_it_quadc_idx)', ...
    ar_it_linh_idx, ar_fl_linh(ar_it_linh_idx)', ...
    ar_it_refh_idx, ar_fl_refh(ar_it_refh_idx)'];
% Sort by a and z
mt_paramsmesh_long = sortrows(mt_paramsmesh_long, [1,3, 5]);

Generate a table with Column names:

% Create Table
tb_paramsmesh_long = array2table(mt_paramsmesh_long);
cl_col_names_a = {'quadc_idx', 'quadc_val', 'linh_idx', 'linh_val', 'refh_idx', 'rehfh_val'};
tb_paramsmesh_long.Properties.VariableNames = cl_col_names_a;
disp(tb_paramsmesh_long);

    quadc_idx    quadc_val    linh_idx    linh_val    refh_idx    rehfh_val
    _________    _________    ________    ________    ________    _________

        1          -0.01         1          0.01         1          -0.01  
        1          -0.01         1          0.01         2          -0.05  
        1          -0.01         2          0.05         1          -0.01  
        1          -0.01         2          0.05         2          -0.05  
        2         -0.001         1          0.01         1          -0.01  
        2         -0.001         1          0.01         2          -0.05  
        2         -0.001         2          0.05         1          -0.01  
        2         -0.001         2          0.05         2          -0.05  

1.3 Cells

1.3.1 Matlab Cell Array Basic Operations

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.3.1.1 String Combine with string cell

ls_st_param_key = {'fl_crra', 'fl_beta', ...
                   'fl_w', 'fl_r_save', ...
                   'fl_a_max', 'it_z_n', 'it_a_n'};
cl_st_param_keys = {'fl_wad', 'fl_betart', 'it_z_nfg'};
st_param = 'asdjfl';
disp([{st_param}, ls_st_param_key, cl_st_param_keys]);

  Columns 1 through 10

    {'asdjfl'}    {'fl_crra'}    {'fl_beta'}    {'fl_w'}    {'fl_r_save'}    {'fl_a_max'}    {'it_z_n'}    {'it_a_n'}    {'fl_wad'}    {'fl_betart'}

  Column 11

    {'it_z_nfg'}

1.3.2 Matlab List Comprehension with Cells

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.3.2.1 Concatenate Numeric Values as String with Trimming

There is a list of numbers, combine (paste) to single string with some connector, trim each element to eliminate spaces.

rng(123,'philox')
ar_rand = rand([5,1]);
st_fl_rand = string(num2str(ar_rand));
st_untrimmmed = strjoin(st_fl_rand, "#");
cl_st_trimmmed = cellfun(@(x) strtrim(x), cellstr(st_fl_rand), 'UniformOutput', false);
st_trimmmed = strjoin(string(cl_st_trimmmed), "#");
disp(['st_untrimmmed:' st_untrimmmed]);

    "st_untrimmmed:"    "  0.53162##  0.60704##  0.31843#0.0016474##  0.65784"

disp(['st_trimmmed:' st_trimmmed]);

    "st_trimmmed:"    "0.53162#0.60704#0.31843#0.0016474#0.65784"

1.3.2.2 Find Index of Elements of String Cells in a larger String Cells

the function below returns the position of cl_st_param_keys in ls_st_param_key should only include in cl_st_param_keys strings that also exist in ls_st_param_key.

ls_st_param_key = {'fl_crra', 'fl_beta', ...
                   'fl_w', 'fl_r_save', ...
                   'fl_a_max', 'it_z_n', 'it_a_n'};

cl_st_param_keys = {'fl_w', 'fl_beta', 'it_z_n'};

cell2mat(cellfun(@(m) find(strcmp(ls_st_param_key, m)), ...
                 cl_st_param_keys, 'UniformOutput', false))

ans = 1x3    
     3     2     6

1.3.2.3 Given Container of Arrays, Find Total Length of All Arrays for Selected Keys

cl_st_param_keys = {'fl_crra', 'fl_beta'};

param_tstar_map = containers.Map('KeyType','char', 'ValueType','any');
it_simu_vec_len = 5;

param_tstar_map('fl_crra') = linspace(1, 2, 5);
param_tstar_map('fl_beta') = linspace(0.94, 0.98, 10);
param_tstar_map('w') = linspace(1.1, 1.4, it_simu_vec_len);
param_tstar_map('r') = linspace(0.01, 0.04, it_simu_vec_len);

ar_it_array_len = cell2mat(cellfun(@(m) length(param_tstar_map(m)), ...
                           cl_st_param_keys, 'UniformOutput', false));

it_total_length = sum(ar_it_array_len);
disp(['ar_it_array_len: ' num2str(ar_it_array_len)])

ar_it_array_len: 5  10

disp(['it_total_length: ' num2str(it_total_length)])

it_total_length: 15

1.3.2.4 Given Container of Arrays, Find Min and Max of Each and Draw Random N sets

cl_st_param_keys = {'fl_crra', 'fl_beta'};

param_tstar_map = containers.Map('KeyType','char', 'ValueType','any');
it_simu_vec_len = 5;

param_tstar_map('fl_crra') = linspace(1, 2, 5);
param_tstar_map('fl_beta') = linspace(0.94, 0.98, 10);
param_tstar_map('w') = linspace(1.1, 1.4, it_simu_vec_len);
param_tstar_map('r') = linspace(0.01, 0.04, it_simu_vec_len);

rng(123);
it_simu_length = 20;
mt_param_rand = cell2mat(cellfun(@(m) ...
                           rand([it_simu_length,1]).*(max(param_tstar_map(m)) - min(param_tstar_map(m))) ...
                           + min(param_tstar_map(m)), ...
                           cl_st_param_keys, 'UniformOutput', false));

tb_rand_draws = array2table(mt_param_rand, 'VariableNames', cl_st_param_keys);

disp(tb_rand_draws);

    fl_crra    fl_beta
    _______    _______

    1.5316     0.97337
     1.607     0.97305
    1.3184     0.94644
    1.0016     0.97349
    1.6578     0.94983
    1.7505     0.97152
    1.7407     0.94277
    1.7108     0.94781
    1.3542     0.97625
    1.1479     0.95709
    1.8834     0.94962
    1.1274     0.96042
    1.2132     0.96637
    1.0676     0.94936
    1.4318     0.96911
    1.3791     0.97365
    1.9399     0.94242
    1.6369     0.96946
    1.9791     0.95752
    1.5709     0.96145

1.3.3 All Possible Combinations of Multiple Arrays

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.3.3.1 Given Several Arrays of Possibly different Length in Container, all Possible combinations

param_tstar_map = containers.Map('KeyType','char', 'ValueType','any');
param_tstar_map('a') = linspace(1, 5, 5);
param_tstar_map('b') = linspace(0.87, 0.97, 6);
param_tstar_map('c') = linspace(0, 0.5, 10);

cl_st_param_keys = {'a','c'};
cl_ar_param_subset_values = values(param_tstar_map, {'a','c'});

cl_mt_all = cl_ar_param_subset_values;
[cl_mt_all{:}] = ndgrid(cl_ar_param_subset_values{:});
mt_param_vals_combi = cell2mat(cellfun(@(m) m(:), cl_mt_all, 'uni', 0));

tb_all_combi = array2table(mt_param_vals_combi, 'VariableNames', cl_st_param_keys);

disp(tb_all_combi);

    a       c    
    _    ________

    1           0
    2           0
    3           0
    4           0
    5           0
    1    0.055556
    2    0.055556
    3    0.055556
    4    0.055556
    5    0.055556
    1     0.11111
    2     0.11111
    3     0.11111
    4     0.11111
    5     0.11111
    1     0.16667
    2     0.16667
    3     0.16667
    4     0.16667
    5     0.16667
    1     0.22222
    2     0.22222
    3     0.22222
    4     0.22222
    5     0.22222
    1     0.27778
    2     0.27778
    3     0.27778
    4     0.27778
    5     0.27778
    1     0.33333
    2     0.33333
    3     0.33333
    4     0.33333
    5     0.33333
    1     0.38889
    2     0.38889
    3     0.38889
    4     0.38889
    5     0.38889
    1     0.44444
    2     0.44444
    3     0.44444
    4     0.44444
    5     0.44444
    1         0.5
    2         0.5
    3         0.5
    4         0.5
    5         0.5

1.3.4 Nested Cells

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.3.4.1 Nested Cells and access

cl_st_param_keys = {'fl_crra', 'fl_beta'};

it_simu_vec_len = 3;
clns_parm_tstar = cell([4,1]);
clns_parm_tstar{1} = {'fl_crra', 'CRRA', linspace(1, 2, it_simu_vec_len)};
clns_parm_tstar{2} = {'fl_beta', 'Discount', linspace(0.94, 0.98, it_simu_vec_len)};
clns_parm_tstar{3} = {'w', 'Wage', linspace(1.1, 1.4, it_simu_vec_len)};
clns_parm_tstar{4} = {'r', 'Save Interest', linspace(0.01, 0.04, it_simu_vec_len)};

disp(clns_parm_tstar(1));

    {1x3 cell}

disp(clns_parm_tstar{1}{1})

fl_crra

disp(clns_parm_tstar{1}{2});

CRRA

disp(clns_parm_tstar{1}{3});

    1.0000    1.5000    2.0000

1.4 Characters and Strings

1.4.1 Basic String Operations, Display, Search, Join and Split

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.4.1.1 Date String

Generate a string based on date and time as file suffix.

st_file_suffix = ['_d' datestr(now,'yymmdd_tHHMMSS')];
disp(st_file_suffix);

_d210701_t094001

1.4.1.2 Combine String, Numeric values etc, Single and Double Quotes

Convert a string array into a single string, note the double quotes, and the auto space between:

st_a = "another string";
ar_st = ["abc", num2str(2), "opq", st_a];
disp(strjoin(ar_st));

abc 2 opq another string

If we do not want to have spaces between words, the second parameter for strjoin allows for string connectors:

st_a = "another string";
ar_st = ["abc", num2str(2), "opq", st_a];
disp(strjoin(ar_st, ""));

abc2opqanother string

With single quotes, the str element is not an array, so does not need strjoin, but not need to have spaces:

st_a = 'another string';
str = ['abc ', num2str(2), ' opq ', st_a];
disp((str));

abc 2 opq another string

1.4.1.3 Construct String Print Statement with String and Numeric Elements

In the example below, we have a number of strings we want to put inside a string array, then join with strjoin, but two of the strings need to be constructed as strings first. Note below that double quoates are own strings, single quotes in brackets constructing additional strings.

st_a = "another string";
ar_st = ["abc", "efg"];
ar_fl_vals = rand([1,3]);
st_print = strjoin(...
    ["Completed SNW_DS_MAIN:", ...
    ['SNW_MP_PARAM=' num2str(123)], ...
    ['SNW_MP_CONTROL=' num2str(678)], ...
    ['STR_VAR1=' char('string')], ...
    ['STR_VAR2=' char(strjoin(ar_st, "-"))], ...
    ['STR_VAR3:;' char(strjoin(ar_st, ";"))], ...
    ['ar_st:;' char(strjoin(strcat( ...
    num2str((1:length(ar_st))', '%0.3d'), '=', ar_st' ...
    ), ";"))], ...
    ['ar_fl_vals:;' strjoin(string(strcat( ...
    num2str((1:length(ar_fl_vals))', '%0.3d'), '=', num2str(ar_fl_vals', '%3.2f'))), ";")], ...
    ], ";");
% Ways to print
st_out = st_print;
ar_ch_out = char(strsplit(st_print,";")');
ar_st_out = strsplit(st_print,";")';
% Print
disp(st_out);

Completed SNW_DS_MAIN:;SNW_MP_PARAM=123;SNW_MP_CONTROL=678;STR_VAR1=string;STR_VAR2=abc-efg;STR_VAR3:;abc;efg;ar_st:;001=abc;002=efg;ar_fl_vals:;;001=0.87;002=0.25;003=0.48

disp(ar_ch_out);

Completed SNW_DS_MAIN:
SNW_MP_PARAM=123      
SNW_MP_CONTROL=678    
STR_VAR1=string       
STR_VAR2=abc-efg      
STR_VAR3:             
abc                   
efg                   
ar_st:                
001=abc               
002=efg               
ar_fl_vals:           
001=0.87              
002=0.25              
003=0.48              

disp(ar_st_out);

    "Completed SNW_DS_MAIN:"
    "SNW_MP_PARAM=123"
    "SNW_MP_CONTROL=678"
    "STR_VAR1=string"
    "STR_VAR2=abc-efg"
    "STR_VAR3:"
    "abc"
    "efg"
    "ar_st:"
    "001=abc"
    "002=efg"
    "ar_fl_vals:"
    "001=0.87"
    "002=0.25"
    "003=0.48"

1.4.1.4 Paste Join Strings Together with Separator

Join strings together with separator, this is similar to the paste0 function in R.

ar_st = ["abc", "efg", "opq"];
disp(strjoin(ar_st, '-'));

abc-efg-opq

1.4.1.5 Combine Char with Numeric Value

Compose a string with words and numerical values

st_title = strcat("Figure Title ", ...
    "(", ...
    "threedeci=%.3f,", ...
    "twodeci=%.2f,", ...
    "int=%.0f", ...
    ")");
ar_params = 123.4567 + zeros(1,3);
st_combo = compose(st_title, ar_params);
disp(st_combo);

Figure Title (threedeci=123.457,twodeci=123.46,int=123)

1.4.1.6 Search if String Contains Substring

Does string contain substring?

st_long1 = 'simu_dense';
st_long2 = 'simu_denser';
st_long3 = 'simuverydense';
st_long4 = 'simu_medium';
st_long5 = 'simuverysmall';
disp([contains(st_long1, 'dense'), contains(st_long2, 'dense'), contains(st_long3, 'dense'), ...
    contains(st_long4, 'dense'), contains(st_long5, 'dense')]);

   1   1   1   0   0

1.4.1.7 Find Elements of an Array that Matches Any Elements of Another Array

There is an array of strings, check if each element equals values specified in another string, using the match function.

% String array from strings
ar_st_long = string({st_long1, st_long2, st_long3, st_long4, st_long5});
% If matches simu_dense
disp(matches(ar_st_long, 'simu_dense'));

   1   0   0   0   0

% If matches simu_dense or simu_denser
disp(matches(ar_st_long, ["simu_dense", "simu_denser"]));

   1   1   0   0   0

1.4.1.8 Change File Name MLX to M

st_file_name_mlx = 'continuous_differentiable.mlx';
at_st_split_file_name = split(st_file_name_mlx, ".");
st_file_name_m = strcat(at_st_split_file_name{1}, '_m.m');
disp(st_file_name_m);

continuous_differentiable_m.m

1.4.2 String Array Manipulations, Join, Find, Replace and the Alphabet

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.4.2.1 Generate a String Array from Strings

Empty String Array and fill with values.

ar_st_titles = strings([3,1]);
ar_st_titles(1) = 'Title1';
ar_st_titles(2) = 'Title2';
ar_st_titles(3) = 'Title3';
disp(ar_st_titles);

    "Title1"
    "Title2"
    "Title3"

Three title lines, with double quotes:

ar_st_titles = ["Title1","Title2","Title3"]';
disp(ar_st_titles);

    "Title1"
    "Title2"
    "Title3"

Three words, joined together, now single quotes, this creates one string, rather than a string array:

st_titles = ['Title1','Title2','Title3'];
disp(st_titles);

Title1Title2Title3

Given some previously defined chars or strings with single or double quotes, not sure which. To safely generate a string array, wrap in brackets and then conver with string function. This generates a string array whether the original inputs were single or double quoted:

st_a = 'a';
st_b = 'b';
st_c = 'c';
st_a_dq = "a";
st_b_dq = "b";
st_c_dq = "c";
ar_st_singlequotes = string({st_a, st_b, st_c});
ar_st_doublequotes = string({st_a_dq, st_b_dq, st_c_dq});
disp(["st_singlequotes" ar_st_singlequotes]);

    "st_singlequotes"    "a"    "b"    "c"

disp(["ar_st_doublequotes" ar_st_doublequotes]);

    "ar_st_doublequotes"    "a"    "b"    "c"

Convert the string array to a cell string array

disp(cellstr(ar_st_doublequotes));

    {'a'}    {'b'}    {'c'}

1.4.2.2 String Cell Array

Create a string array:

ar_st_title_one = {'Title One Line'};
ar_st_titles = {'Title1','Title2','Title3'};
disp(ar_st_title_one);

    {'Title One Line'}

disp(ar_st_titles);

    {'Title1'}    {'Title2'}    {'Title3'}

Add to a string array:

ar_st_titles{4} = 'Title4';
disp(ar_st_titles);

    {'Title1'}    {'Title2'}    {'Title3'}    {'Title4'}

Update one of the strings:

ar_st_title_one{1} = strcat('log(', ar_st_title_one{1},')');
ar_st_titles{1} = strcat('log(', ar_st_titles{1},')');
disp(ar_st_title_one);

    {'log(Title One Line)'}

disp(ar_st_titles);

    {'log(Title1)'}    {'Title2'}    {'Title3'}    {'Title4'}

1.4.2.3 Joint String Cell Array with Suffix

ar_st_titles = {'Title1','Title2','Title3'};
disp(strcat(ar_st_titles, '_init'));

    {'Title1_init'}    {'Title2_init'}    {'Title3_init'}

1.4.2.4 Duplicate String

it_duplicate_n = 10;
disp(repmat({'String'}, [1, it_duplicate_n]));

  Columns 1 through 9

    {'String'}    {'String'}    {'String'}    {'String'}    {'String'}    {'String'}    {'String'}    {'String'}    {'String'}

  Column 10

    {'String'}

1.4.2.5 String Join to form Single Element

using char() is safe

st_var_name = "abc"

st_var_name = "abc"

st_var_name = [st_var_name ' percentile values']

st_var_name = 1x2 string    
"abc"        " percentile values"    

strjoin(st_var_name)

ans = "abc  percentile values"


st_var_name = "abc"

st_var_name = "abc"

st_var_name = [char(st_var_name) ' percentile values']

st_var_name = 'abc percentile values'


st_var_name = 'abc'

st_var_name = 'abc'

st_var_name = [char(st_var_name) ' percentile values']

st_var_name = 'abc percentile values'

1.4.2.6 String Join dash (Paste)

This is similar to R’s paste function:

st_var_name = "abc";
st_var_name = [st_var_name, 'efg', 'mqo'];
disp(strjoin(st_var_name, "_"));

abc_efg_mqo

disp(strjoin(st_var_name, ","));

abc,efg,mqo

1.4.2.7 Numeric Array to String without Space

String replace

ar_it_test_grp = [3, 8, 9];
strrep(num2str(ar_it_test_grp), '  ', '_')

ans = '3_8_9'

1.4.2.8 Substring replace in Cell Array

ar_st_cells = {'shock=0.35','shock=0.40','shock=0.46'};
ar_st_updated_cells = strrep(ar_st_cells, 'shock', '$\epsilon$');
disp(ar_st_updated_cells);

    {'$\epsilon$=0.35'}    {'$\epsilon$=0.40'}    {'$\epsilon$=0.46'}

1.4.2.9 Find position of String in String Cell

ls_st_param_key = {'fl_crra', 'fl_beta', ...
                   'fl_w', 'fl_r_save', ...
                   'fl_a_max', 'it_z_n', 'it_a_n'};
st_param_key = 'fl_a_max';
find(strcmp(ls_st_param_key, st_param_key))

ans = 5

1.4.2.10 Find the positions of String Cells in Full String Cells

Find the positions of fl_w, fl_beta, and it_z_n in ls_st_param_key. Then just find the position of fl_crra. When looking for the position of something that does not exist, generate an find outcome array of length 0.

ls_st_param_key = {'fl_crra', 'fl_beta', ...
                   'fl_w', 'fl_r_save', ...
                   'fl_a_max', 'it_z_n', 'it_a_n'};

cl_st_param_keys = {'fl_w', 'fl_beta', 'it_z_n'};

cell2mat(cellfun(@(m) find(strcmp(ls_st_param_key, m)), ...
                 cl_st_param_keys, 'UniformOutput', false))

ans = 1x3    
     3     2     6

find(strcmp(ls_st_param_key, 'fl_crra'))

ans = 1

length(find(strcmp(ls_st_param_key, 'fl_crra_not_exist')))

ans = 0

~sum(strcmp(ls_st_param_key, 'fl_crra_not_exist'))

ans = 
   1

1.4.2.11 Cell to string Paste and Replace dash

cl_st_param_keys = {'fl_crra', 'fl_beta'};
display(strrep(strjoin(cl_st_param_keys, '-'), '_', '\_'));

fl\_crra-fl\_beta

1.4.2.12 Generate Alphebetical String Array from A to Z

Generate a single string that is A to Z, then generate this as a string array.

% a to z single string
st_a2z = 'a':'z';
% a to z array of letters
ar_st_a2z = string(('A':'Z')')';
% Display
disp(st_a2z);

abcdefghijklmnopqrstuvwxyz

disp(ar_st_a2z);

  Columns 1 through 18

    "A"    "B"    "C"    "D"    "E"    "F"    "G"    "H"    "I"    "J"    "K"    "L"    "M"    "N"    "O"    "P"    "Q"    "R"

  Columns 19 through 26

    "S"    "T"    "U"    "V"    "W"    "X"    "Y"    "Z"

1.4.3 Convert and Concatenate Strings Arrays with Numbers and Number Arrays with Strings

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.4.3.1 Generate a String from Numeric Array and Print on Screen with Counter

Want to quickly print on screen an array of number with the array name and a counter printed before each value.

% An array of numbers to print
rng(123);
ar_fl_values = rand(5,1);
% A string array of counters with leading zeros for even display
ar_st_counter_leading0 = num2str((1:length(ar_fl))', '%0.3d');
% A float array of value formatted
ar_fl_values_formated = num2str(ar_fl', '%3.2f');
ar_ch_values_display = strcat('fl_val, c', ar_st_counter_leading0, '=', ar_fl_values_formated);
% print
disp(ar_ch_values_display);

fl_val, c001=0.78
fl_val, c002=0.29
fl_val, c003=0.31
fl_val, c004=0.67
fl_val, c005=0.11
fl_val, c006=0.66
fl_val, c007=0.89
fl_val, c008=0.70
fl_val, c009=0.44
fl_val, c010=0.44

1.4.3.2 Combine A String Array with a Numeric Array using Compose

String array and numeric array, combine together using the compose function, and test different formatting functions. Formating with leading empty spaces, leading zeros, and convert to integer or not.

st_titles = ["%.3f",   "%.1f",   "%.0f";...
             "%6.3f",  "%6.1f",  "%6.0f";...
             "%06.3f", "%06.1f", "%06.0f"];
ar_params = 123.4567890 + zeros(3,3);
st_combo = compose(st_titles, ar_params);
disp(st_combo);

    "123.457"    "123.5"     "123"   
    "123.457"    " 123.5"    "   123"
    "123.457"    "0123.5"    "000123"

A string array and a numeric array combined

ls_st_param_esti = {'ar_mu_pos_1', 'ar_COEF_U_gamma'};
ar_params = [1213,456];
st_combo = strcat(ls_st_param_esti', '=', num2str(ar_params'));
disp(st_combo);

    {'ar_mu_pos_1=1213'    }
    {'ar_COEF_U_gamma= 456'}

1.4.3.3 Numeric Array to String Array with Decimal Formatting

There is a numeric array, format with a certain number of decimal points, and convert to string array.

% Inputs
rng(123);
ar_params = [1.23324, 493.1232, 4994.1111, 123];
st_rounding = '.3f';
% Rounding and to string array
ar_st_params = compose(strcat("%", st_rounding), ar_params);
% Display:
disp(ar_st_params);

    "1.233"    "493.123"    "4994.111"    "123.000"

1.4.3.4 Title from an Array of Values

There is a vector of parameter values and a vector of names for these parameter values, I want to include these in the title of a figure with the same decimal formating.

% Inputs
rng(123);
ar_params = rand(1,3);
ar_st_parms_names = ["param1", "param2", "param3"];
st_rounding = '.2f';
st_title_main = "this is the figure title";
% Rounding and combining
ar_st_params = strcat(ar_st_parms_names, compose(strcat("=%", st_rounding), ar_params));
% Generate a Single String that is comma separated:
st_param_pasted = strjoin(ar_st_params, ', ');
% Generate title with parameters
st_title_wth_params = strcat(st_title_main, ' (', st_param_pasted, ')');
% Display:
disp(st_title_wth_params);

this is the figure title (param1=0.70, param2=0.29, param3=0.23)

1.4.3.5 Combine String with Numeric Array

Example 1:

ar_fl_abc1 = [0.4 0.1 0.25 0.3 0.4];
disp([num2str(ar_fl_abc1', 'zw=%3.2f;'), num2str(ar_fl_abc1', 'zr=%3.2f')]);

zw=0.40;zr=0.40
zw=0.10;zr=0.10
zw=0.25;zr=0.25
zw=0.30;zr=0.30
zw=0.40;zr=0.40

Example 2:

close all;

rng(123);
ar_z_r_borr_mesh_wage = rand([1,5]);
ar_z_wage_mesh_r_borr = rand([1,5]);
ar_it_rows = round(rand([1,5])*10);
cl_st_full_rowscols = cellstr([num2str(ar_z_r_borr_mesh_wage', 'zr=%3.2f;'), ...
                               num2str(ar_z_wage_mesh_r_borr', 'zw=%3.2f')]);
cl_col_names = strcat('zi=', num2str(ar_it_rows([1,3,5])'), ':', cl_st_full_rowscols([1,3,5]));
disp(ar_z_r_borr_mesh_wage);

    0.6965    0.2861    0.2269    0.5513    0.7195

disp(ar_z_wage_mesh_r_borr);

    0.4231    0.9808    0.6848    0.4809    0.3921

disp(cl_st_full_rowscols);

    {'zr=0.70;zw=0.42'}
    {'zr=0.29;zw=0.98'}
    {'zr=0.23;zw=0.68'}
    {'zr=0.55;zw=0.48'}
    {'zr=0.72;zw=0.39'}

disp(cl_col_names);

    {'zi=3:zr=0.70;zw=0.42'}
    {'zi=4:zr=0.23;zw=0.68'}
    {'zi=4:zr=0.72;zw=0.39'}

1.4.3.6 Combine Number with String Cell Array

We have a string cell array we created from the previous section, now append numbers to it

% Append Common Numbers
cl_col_names_append = strcat(cl_col_names, '-String-Cell-With-Numeric-', num2str(123));
disp(cl_col_names_append);

    {'zi=3:zr=0.70;zw=0.42-String-Cell-With-Numeric-123'}
    {'zi=4:zr=0.23;zw=0.68-String-Cell-With-Numeric-123'}
    {'zi=4:zr=0.72;zw=0.39-String-Cell-With-Numeric-123'}

1.4.3.7 Combine Numeric Array with String Cell Array

Append an array of numeric values

% Append Common Numbers
cl_col_names_append = strcat(cl_col_names, '-String-Cell-With-Numeric-Array-', ...
    num2str(transpose(1:length(cl_col_names))));
disp(cl_col_names_append);

    {'zi=3:zr=0.70;zw=0.42-String-Cell-With-Numeric-Array-1'}
    {'zi=4:zr=0.23;zw=0.68-String-Cell-With-Numeric-Array-2'}
    {'zi=4:zr=0.72;zw=0.39-String-Cell-With-Numeric-Array-3'}

1.4.3.8 Convert Numeric Array to String, Apeend Prefix to all elements.

ar_fl_abc1 = [0.4 0.1 0.25 0.3 0.4];
ar_st_wth_prefix = strcat('row=', string(ar_fl_abc1));
disp(ar_st_wth_prefix);

    "row=0.4"    "row=0.1"    "row=0.25"    "row=0.3"    "row=0.4"


% Does Array Exist in Longer Array as Subset
ar_abc1 = [0.4 0.1 0.25 0.3 0.4];
ar_abc2 = [0.4 0.1 0.2 0.3 0.4];
ar_efg = [0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.4];
st_abc1 = strjoin(string(num2str(ar_abc1)));
st_abc2 = strjoin(string(num2str(ar_abc2)));
st_efg = strjoin(string(num2str(ar_efg)));
contains(st_efg, st_abc1)

ans = 
   0

contains(st_efg, st_abc2)

ans = 
   1


% Display Convert to String
fprintf('Display string [%s]', num2str([1,2,3]));

Display string [1  2  3]

fprintf('Display string [%s]', num2str(1.1));

Display string [1.1]

fprintf('Display string [%s]', 'abc');

Display string [abc]

1.5 Map Containers

1.5.1 Container Map Basics

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.5.1.1 Generate a Container map with any Type of data

Create a container map with float, int, string, and matrix

close all;
clear all;

% Create A Map with String Keys and any values
param_map = containers.Map('KeyType','char', 'ValueType','any');
param_map('share_unbanked_j') = 12;
param_map('equi_r_j') = 2;
param_map('equi_w_j') = 'abc';
param_map('equi_P_j') = zeros(2,3);
disp(param_map.keys);

    {'equi_P_j'}    {'equi_r_j'}    {'equi_w_j'}    {'share_unbanked_j'}

disp(param_map.values);

    {2x3 double}    {[2]}    {'abc'}    {[12]}

1.5.1.2 Access Multiple Values of a container map

Values been accessed need to be of the same type

% Parameter Dealing from Map
params_group = values(param_map, {'share_unbanked_j', 'equi_r_j'});
[equi_P_j, equi_r_j] = params_group{:};
disp(['equi_P_j:' num2str(equi_P_j) ', equi_r_j:' num2str(equi_r_j)]);

equi_P_j:12, equi_r_j:2

% Access Scalar Elements of Map and Convert the Array
disp(cell2mat(values(param_map, {'share_unbanked_j', 'equi_r_j'})));

    12     2

Create a container map of color values and generate a array of color choices:

% Container map with three colors
mp_colors = containers.Map('KeyType', 'char', 'ValueType', 'any');
mp_colors('blue')   = [57 106 177]./255;
mp_colors('red')    = [204 37 41]./255;
mp_colors('black')  = [83 81 84]./255;
% An selection array
ar_st_colors_pick = {'blue', 'blue', 'red', 'black', 'blue'};
ar_colors = values(mp_colors, ar_st_colors_pick);
% Print selected colors
celldisp(ar_colors);


ar_colors{1} =
 
    0.2235    0.4157    0.6941



ar_colors{2} =
 
    0.2235    0.4157    0.6941



ar_colors{3} =
 
    0.8000    0.1451    0.1608



ar_colors{4} =
 
    0.3255    0.3176    0.3294



ar_colors{5} =
 
    0.2235    0.4157    0.6941

1.5.1.3 Container Integer Keys

Given some matrix, I want to store matrix column names as well as labels for what each row and column correspond to. Achieve this using a cell array of container maps. Cell dimensions correspond to the first, second, etc dimensions, any dimension specific information can be stored in this fashion.

Can access information asssociated with the label value of the row values:

% Define Matrix Row and Column and additional dimension information
cl_mp_datasetdesc = {};
cl_mp_datasetdesc{1} = containers.Map({'dim', 'name', 'labval'}, {1, 'kids', [0,1,2,3]});
cl_mp_datasetdesc{2} = containers.Map({'dim', 'name', 'labval'}, {2, 'age', [18,19,20]});
% get variable labels for the first dimension (rows)
disp([...
    string(['dim 1 var name:' cl_mp_datasetdesc{1}('name') ]), ...
    string(['dim 2 var name:' cl_mp_datasetdesc{2}('name') ])...
    ]);

    "dim 1 var name:kids"    "dim 2 var name:age"

1.5.1.4 Is Key In Container

param_map_a = containers.Map('KeyType','char', 'ValueType','any');
param_map_a('fl_b_bd') = -3;
param_map_a('fl_w_max') = 50;
param_map_a('fl_kp_min') = 0;
param_map_a('it_w_i') = 100;

disp([...
    string(['has it_w_i as key? ' num2str(isKey(param_map_a, 'it_w_i'))]), ...
    string(['has it_w_i1 as key? ' num2str(isKey(param_map_a, 'it_w_i1'))]) ...
    ]);

    "has it_w_i as key? 1"    "has it_w_i1 as key? 0"

1.5.1.5 Container Key Loop

Generate new container key within loop dynamically

param_map_a = containers.Map('KeyType', 'char', 'ValueType','any');
rng('default');
rng(123);
for st_cur = ["abc", "efg", "qqq"]

    if (strcmp(st_cur, "abc"))
       data = rand([1,1]);
    elseif (strcmp(st_cur, "efg"))
       data = 123.123;
    elseif (strcmp(st_cur, "qqq"))
       data = -123;
    end

    % common function
    fl_sh_0p1pc_j = data*2 + 1;
    fl_sh_5pc_j = data/2 - 1;

    % generate map keys
    st_key_sh_0p1pc_j = strjoin([st_cur, 'sh_0p1pc_j'], "_");
    st_key_sh_5pc_j = strjoin([st_cur, 'sh_5pc_j'], "_");

    % store
    param_map_a(st_key_sh_0p1pc_j) = fl_sh_0p1pc_j;
    param_map_a(st_key_sh_5pc_j) = fl_sh_5pc_j;

end

disp([...
    string(['param_map_a.keys:' param_map_a.keys]), ...
    string(['param_map_a.values:' string(param_map_a.values)]) ...
    ]);

  Columns 1 through 7

    "param_map_a.keys:"    "abc_sh_0p1pc_j"    "abc_sh_5pc_j"    "efg_sh_0p1pc_j"    "efg_sh_5pc_j"    "qqq_sh_0p1pc_j"    "qqq_sh_5pc_j"

  Columns 8 through 14

    "param_map_a.values:"    "2.3929"    "-0.65177"    "247.246"    "60.5615"    "-245"    "-62.5"

1.5.2 Container Map Display Swtich Key and Values and Subseting

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.5.2.2 Given Map Switch Keys and Values

Given the container map below, switch so that keys become values and values become keys.

First, this is the map that uses strings as keys and index as values:

mp_param_idx = containers.Map('KeyType','char', 'ValueType','any');
mp_param_idx('parm_sk_mean') = 1;
mp_param_idx('parm_sk_sd') = 2;
mp_param_idx('NPquad') = 3;
mp_param_idx('gamma') = 4;
mp_param_idx('HAquad') = 5;
mp_param_idx('theta') = 6;

Second, get the keys and the values, convert the values to string:

param_map_paramNames = keys(mp_param_idx);
param_map_paramIndex_int = values(mp_param_idx);
% convert cell of int to cell of string
param_map_paramIndex_str = cellfun(@(idx) num2str(idx(:)), param_map_paramIndex, 'uni', 0);

Third, generate new Map:

mp_idx_params = containers.Map(param_map_paramIndex_str, param_map_paramNames);
param_map_keys = keys(mp_idx_params);
param_map_vals = values(mp_idx_params);
for i = 1:length(mp_idx_params)
    st_key = param_map_keys{i};
    ob_val = param_map_vals{i};
    st_display = strjoin(['pos =' num2str(i) '; key =' string(st_key) '; val =' string(ob_val)]);
    disp(st_display);
end

pos = 1 ; key = 1 ; val = parm_sk_mean
pos = 2 ; key = 2 ; val = parm_sk_sd
pos = 3 ; key = 3 ; val = NPquad
pos = 4 ; key = 4 ; val = gamma
pos = 5 ; key = 5 ; val = HAquad
pos = 6 ; key = 6 ; val = theta

Overall, code together shorter:

% Single call to convert
mp_idx_params_oneline = containers.Map(...
    cellfun(@(idx) num2str(idx(:)), values(mp_param_idx), 'uni', 0), ...
    keys(mp_param_idx));
% Check equality
disp(['mp_idx_params_oneline==mp_idx_params:' num2str(mp_idx_params_oneline==mp_idx_params) ])

mp_idx_params_oneline==mp_idx_params:0

1.5.2.3 Select of Subset of Key/Values from a Container Map

There is a larger container map, I want to create a new container map, that keeps a subset of the keys/values of the full container map.

% Original Container map
param_map = containers.Map('KeyType','char', 'ValueType','any');
param_map('equi_r_j') = 0.05;
param_map('equi_w_j') = 1.05;
param_map('equi_P_j') = 1;
% To select a subset of keys
ls_st_keys_select = {'equi_w_j', 'equi_P_j'};
% Select
param_map_subset = containers.Map(ls_st_keys_select, values(param_map, ls_st_keys_select));
% display
disp(param_map_subset.keys);

    {'equi_P_j'}    {'equi_w_j'}

disp(param_map_subset.values);

    {[1]}    {[1.0500]}

1.5.3 Container Map Example Overriding

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.5.3.1 Update Container Map

There is one map with values, Container Map A. There is another container Map, Container Map B. Container Maps A and B share keys. For keys that exist in B and A, B Key value supercede values for the same keys in A. For new keys in B, they superced keys in A.

param_map_a = containers.Map('KeyType','char', 'ValueType','any');
param_map_a('fl_b_bd') = -3;
param_map_a('fl_w_max') = 50;
param_map_a('fl_kp_min') = 0;
param_map_a('it_w_i') = 100;

param_map_b = containers.Map('KeyType','char', 'ValueType','any');
param_map_b('fl_w_max') = 77;
param_map_b('fl_kp_min') = -231;
param_map_b('it_z_n') = 5;
param_map_b('fl_z_mu') = 0;

param_map_c = [param_map_a; param_map_b];
param_map_c.keys

ans = 
    {'fl_b_bd'}    {'fl_kp_min'}    {'fl_w_max'}    {'fl_z_mu'}    {'it_w_i'}    {'it_z_n'}

param_map_c.values

ans = 
    {[-3]}    {[-231]}    {[77]}    {[0]}    {[100]}    {[5]}

1.6 Map Structure Array

1.6.1 Maplab Nested Container Map with Struct

Go back to fan’s MEconTools Package, Matlab Code Examples Repository (bookdown site), or Math for Econ with Matlab Repository (bookdown site).

1.6.1.1 A Struct of Model Parameters with Different Information

There is a list of model parameters, there are various information we store for each parameter. Store each type of information in a different container map, and then combine them together in a struct. This is more flexible than generating a table, and can be called with a single line. This is effectively a nested container, imagine if we define for each parameter a map with keys indicating different types of information. Rather than doing that, the keys are elements of the struct, each key/value is in a different container.

% index for different parameters
mp_param_idx = containers.Map('KeyType','char', 'ValueType','any');
mp_param_idx('NPquad') = 3;
mp_param_idx('gamma') = 4;
mp_param_idx('HAquad') = 5;
mp_param_idx('theta') = 6;
mp_param_idx('lambda') = 7;
mp_param_idx('msrErrProtSD') = 8;
mp_param_idx('logProt') = 9;
mp_param_idx('freePriceFrac') = 10;
mp_param_idx('h_exoshk_sd') = 11;
mp_param_idx('h_endoshk_sd') = 12;

% Invert key and index
mp_idx_params = containers.Map(...
    cellfun(@(idx) num2str(idx(:)), values(mp_param_idx), 'uni', 0), ...
    keys(mp_param_idx));

% Exponentiation Positivity Restrictions
mp_param_explog = containers.Map('KeyType','char', 'ValueType','any');
mp_param_explog('NPquad') = -1;
mp_param_explog('gamma') = 1;
mp_param_explog('lambda') = -1;
mp_param_explog('msrErrProtSD') = 1;
mp_param_explog('freePriceFrac') = 1;
mp_param_explog('h_exoshk_sd') = 1;
mp_param_explog('h_endoshk_sd') = 1;

% Create Struct
param_struct.paramindex = mp_param_idx;
param_struct.paramstring = mp_idx_params;
param_struct.explog = mp_param_explog;

Given the struct contructed, can get the index for a particular parameter, or the explog value in a single line call:

% Get values in single line
disp(['NPquad index=' num2str(param_struct.index('NPquad')) ...
    ', explog=' num2str(param_struct.explog('NPquad'))]);

NPquad index=3, explog=-1

Furthermore, since we have both mp_param_idx and mp_idx_params, suppose we only know the current index, we can use to index to find the string, and use the string to find the expolog value:

% Get the explog value for a particular index
st_param = param_struct.paramstring('11');
it_explog = param_struct.explog(st_param);
% Single line call
disp(['The explog of parameter index 11 is "' ...
    num2str(param_struct.explog(param_struct.paramstring('11'))) ...
    '" (param index 11 is "' st_param '")']);

The explog of parameter index 11 is "1" (param index 11 is "h_exoshk_sd")