Matlab: repeat and concatenate rows and cols into new array - arrays

I have two 4-by-4 arrays:
a1 = [ 1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16 ]
a2 = [ 17 18 19 20; 21 22 23 24; 25 26 27 28; 29 30 31 32 ]
I need to create 16-by-8 array C:
1 2 3 4 17 18 19 20
1 2 3 4 21 22 23 24
1 2 3 4 25 26 27 28
1 2 3 4 29 30 31 32
5 6 7 8 17 18 19 20
5 6 7 8 21 22 23 24
5 6 7 8 25 26 27 28
5 6 7 8 29 30 31 32
9 10 11 12 17 18 19 20
9 10 11 12 21 22 23 24
9 10 11 12 25 26 27 28
9 10 11 12 29 30 31 32
13 14 15 16 17 18 19 20
13 14 15 16 21 22 23 24
13 14 15 16 25 26 27 28
13 14 15 16 29 30 31 32
The left half (from 1st to 4th column) of the result array C should repeat 4 times i-th row of the array a1, the right half (from 5th to 8th column) should repeat 4 times the array a2.
Below is my code.
p=4
n=4
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=1:p
for k=a:b
C(k,j)=a1(i,j);
end;
end;
end;
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=p+1:2*p
l=1;
for k=a:b
C(k,j)=a2(l,j-p);
l=l+1;
end;
end;
end;
C;
size_C=size(C)
Question. Is it possible to create result array C without for-loop? Which functions can I use?

Yes it's possible.
One way of doing it is by using kron and repmat
C = [ kron(a1, ones(4,1)) repmat(a2, 4, 1)]
Perhaps the 4 should be derived from the size of one of the matrixes

You can use ndgrid to generate the row indices and then concatenate:
[ii, jj] = ndgrid(1:size(a2,1), 1:size(a1,1));
C = [a1(jj,:) a2(ii,:)];

With focus on performance, here's one using reshape and repmat -
% Store sizes
M = size(a1,1);
N = size(a2,1);
% Get the replicated version for a1 and a2 separately
parte1 = reshape(repmat(reshape(a1,1,M,[]),[N,1,1]),M*N,[])
parte2 = repmat(a2,[M,1]);
% Do columnar concatenatation for final output
out = [parte1 parte2]
Sample run on a generic case -
a1 = % 3 x 4 array
5 2 6 9
7 4 7 6
9 8 6 1
a2 = % 2 x 5 array
7 7 1 9 2
6 8 8 7 9
out =
5 2 6 9 7 7 1 9 2
5 2 6 9 6 8 8 7 9
7 4 7 6 7 7 1 9 2
7 4 7 6 6 8 8 7 9
9 8 6 1 7 7 1 9 2
9 8 6 1 6 8 8 7 9

Related

A problem with fscanf() in c , overwriting other variables

I'm traying to read from a file two things :
1- a list of integers(on the top of the file) in to an array of integers inputs[]
2- 3 matrixes 5x5 etch into an array of array of array boards[][][]
the firs part works properly but when the 2 part finished some how the inputs[] change values
The code :
void loadfile(const char* filepath,int *inputs ,int boards [nboards][size][size]){
FILE *inp=fopen(filepath,"r");
//loading the marked numbers
for(int i=0;i<4;i++){
fscanf(inp,"%d",inputs+i);
//to show that inputs reseve the the right values at the start
printf("%d ",*(inputs+i));
fseek(inp,ftell(inp)+1,SEEK_SET);
}
printf("\n");
//loaing the boards
for(int n=1;n<=nboards;n++){
for(int i=0;i<size;i++)
for(int j=0;j<size;j++){
fscanf(inp,"%d",&boards[n][i][j]);
printf("%d ",boards[n][i][j]);
}
printf("\n");
}
fclose(inp);
}
int main(){
int inputs[4]={};
int boards[nboards][size][size]={};
loadfile("inputs.txt",inputs,boards);
for(int i=0;i<4;i++)
printf("%d ",*(inputs+i));
}
The file :
7,4,9,5
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
The output:
7 4 9 5
22 13 17 11 0 8 2 23 4 24 21 9 14 16 7 6 10 3 18 5 1 12 20 15 19
3 15 0 2 22 9 18 13 17 5 19 8 7 25 23 20 11 10 24 4 14 21 16 12 6
14 21 17 24 4 10 16 15 9 19 18 8 23 26 20 22 11 13 6 5 2 0 12 3 7
21 17 24 4

Create matrix of some repeating numbers

EN = 10;
etable = [1,2,3,4,5,6;
4,5,6,7,8,9;
7,8,9,10,11,12;
10,11,12,13,14,15;
13,14,15,16,17,18;
16,17,18,19,20,21;
19,20,21,22,23,24;
22,23,24,25,26,27;
25,26,27,28,29,30;
28,29,30,31,32,33];
Is it possible to make a for loop in which I just change the EN value and it automatically creates etable? Because I have to make EN 50 so it'll not be good to write 50 lines in etable.
I tried in this way:
EN = 10;
c = 1:EN;
nodes = zeros(size(c',1),2);
for i = 1:length(c)
nodes(i,1) = i;
nodes(i,2) = i+1;
end
etable = zeros(size(c',1),6);
for i = 1:size(nodes,1)
etable(i,1) = 2*nodes(i,1)-1;
etable(i,2) = 2*nodes(i,1);
etable(i,3) = 2*nodes(i,1)+1;
etable(i,4) = 2*nodes(i,2);
etable(i,5) = 2*nodes(i,2)+1;
etable(i,6) = 2*nodes(i,2)+2;
end
You can use implicit expansion implicitly (introduced in MATLAB R2016b) or explicitly by using MATLAB's bsxfun to create that matrix:
% Parameters
EN = 10;
n = 6;
step = 3;
% Matrix (implict expansion, MATLAB >= R2016b)
etable = (0:step:EN*step-1).' + (1:n)
% Matrix (bsxfun, MATLAB < R2016b)
etable_legacy = bsxfun(#plus, (0:step:EN*step-1).', (1:n))
For the given parameter set, the outputs are:
etable =
1 2 3 4 5 6
4 5 6 7 8 9
7 8 9 10 11 12
10 11 12 13 14 15
13 14 15 16 17 18
16 17 18 19 20 21
19 20 21 22 23 24
22 23 24 25 26 27
25 26 27 28 29 30
28 29 30 31 32 33
etable_legacy =
1 2 3 4 5 6
4 5 6 7 8 9
7 8 9 10 11 12
10 11 12 13 14 15
13 14 15 16 17 18
16 17 18 19 20 21
19 20 21 22 23 24
22 23 24 25 26 27
25 26 27 28 29 30
28 29 30 31 32 33
You can change EN (number of rows), the "number of columns" n and/or the "step between rows" step.
Hope that helps.

Random chose N items from array and update it in BASH SCRIPT

I am trying to random choose a number of items of an array and then update it to do it again till the last set:
#! /bin/bash
A=({1..27})
T=${#A[#]} #number of items in the array
N=3 #number of items to be chosen
V=$(($T/$N)) #number of times to loop
echo ${A[#]} " >> ${#A[#]}"
for ((n=0;n<$V;n++)); do
A1=()
for I in `shuf --input-range=0-$(( ${#A[*]} - 1 )) | head -${N}`; do #random chooses N items random
S=`echo ${A[$I]}` #the chosen items
#echo $S
A1+=("$S|") #creates an array with the chosen items
A=("${A[#]/$S}") #deletes the the chosen items from array
done
echo ${A[#]} " >> ${#A[#]}"
echo ${A1[#]} " >> ${#A1[#]}"
done
The type of output I am getting with this code is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 >> 27
1 4 5 6 7 8 9 10 11 1 1 14 15 16 17 18 19 1 2 4 5 6 7 >> 27
20| 2| 3| >> 3
4 6 7 8 9 0 1 4 6 7 8 9 2 4 6 7 >> 27
1| | 5| >> 3
6 7 8 9 0 1 6 7 8 9 2 6 7 >> 27
| | 4| >> 3
7 8 9 0 1 7 8 9 2 7 >> 27
6| | | >> 3
7 8 9 0 1 7 8 9 7 >> 27
| | 2| >> 3
7 9 0 1 7 9 7 >> 27
8| | | >> 3
7 9 1 7 9 7 >> 27
| | 0| >> 3
7 9 1 7 9 7 >> 27
| | | >> 3
1 >> 27
9| 7| | >> 3
Any ideas why it works fine in the start and fails in the end??
There are some improvements that could be made to your script:
Use lowercase letters
Quote your expansion ("${a[#]}").
Remove items by doing unset a[j].
Re-build array with a=("${a[#]}").
No need for head as shuf could produce a counted result with -n.
Avoid the use of backquotes, use $(…) instead.
That will reduce the script to:
#!/bin/bash
t=27 #number of items in the array
n=3 #number of items to be chosen
a=( $(seq 1 "$t") )
a1=()
while (( ${#a[#]} >= n )); do
for j in $(shuf -n "$n" --input-range=0-$((${#a[#]}-1)) ); do # choose $n random items.
a1+=("${a[j]}") # append to an array the chosen items.
unset "a[j]" # deletes the the chosen items from array.
done
a=("${a[#]}") # re-build the array.
echo "a ${a[#]} >> ${#a[#]}"
echo "a1 ${a1[#]} >> ${#a1[#]}"
done
This will produce this output:
a 1 2 3 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 26 27 >> 24
a1 17 13 4 >> 3
a 1 2 5 6 7 8 10 11 12 14 15 16 18 19 20 21 22 23 24 26 27 >> 21
a1 17 13 4 25 3 9 >> 6
a 1 2 5 6 7 8 10 11 14 15 16 18 21 22 23 24 26 27 >> 18
a1 17 13 4 25 3 9 12 20 19 >> 9
a 1 2 5 7 8 10 11 14 15 16 21 22 24 26 27 >> 15
a1 17 13 4 25 3 9 12 20 19 23 6 18 >> 12
a 2 7 8 10 11 14 15 16 22 24 26 27 >> 12
a1 17 13 4 25 3 9 12 20 19 23 6 18 1 5 21 >> 15
a 2 8 10 14 15 22 24 26 27 >> 9
a1 17 13 4 25 3 9 12 20 19 23 6 18 1 5 21 7 11 16 >> 18
a 2 10 14 24 26 27 >> 6
a1 17 13 4 25 3 9 12 20 19 23 6 18 1 5 21 7 11 16 22 8 15 >> 21
a 14 26 27 >> 3
a1 17 13 4 25 3 9 12 20 19 23 6 18 1 5 21 7 11 16 22 8 15 2 24 10 >> 24
a >> 0
a1 17 13 4 25 3 9 12 20 19 23 6 18 1 5 21 7 11 16 22 8 15 2 24 10 14 26 27 >> 27
But the same array a1 could be built just in one step with shuf:
#!/bin/bash
t=27 # number of items in the array
n=3 # number of items to be chosen
a1=( $(shuf --input-range=1-"$t") )
printf '%3s ' "${a1[#]}"; echo
Which will print:
$ ./script.sh
15 23 1 9 24 2 21 11 12 10 19 25 27 13 5 26 4 7 14 3 22 20 17 18 16 6 8
Or, if the result must be in $n elements per line:
#!/bin/bash
t=27 # number of items in the array
n=3 # number of items to be chosen
a1=( $(shuf --input-range=1-"$t") )
while ((i+n<=t)); do
printf '%3s ' "${a1[#]:i:n}"; echo
((i+=n))
done
Printing:
$ ./script.sh
7 19 16
4 20 26
11 23 2
13 6 15
22 12 25
18 14 10
21 8 9
5 24 27
1 3 17
Looks like a simpler solution.
There are a few wrong things in your script, especially the way you (think you) delete the elements from the array. You're not deleting any elements, you're only replacing their values by the empty string in every field!. That's why your array has 27 elements all the way through, and after the first iteration, all the 2's and 3's are removed from each field. Here's a more idiomatic script:
#! /bin/bash
a=( {1..27} )
n=3 #number of items to be chosen
while ((${#a[#]}>=n)); do
a1=()
for ((i=0;i<n;++i)); do
# pick an index
x=$((RANDOM%${#a[#]}))
# append its value to array a1
a1+=( "${a[x]}" )
# unset it
unset 'a[x]'
# reconstruct array a (make it non-sparse again)
a=( "${a[#]}" )
done
# print array
printf 'a: %s >> %s\n' "${a[*]}" "${#a[#]}"
# print chosen elements
printf 'a1: %s >> %s\n' "${a1[*]}" "${#a1[#]}"
done

How can I find the index of the last greater than or equals value in one array, for all values in the first array? MATLAB

I have 2 vectors. A is a list of dates, every day for 3 years. B is a list of (option expiration) dates, which occur once a month.
A is therefore much larger than B. I want a vector the length of A, which for each entry in A finds the index of the last >= value in B.
In this way I can get an expiration date (from B) for every date in my vector A.
I would like to accomplish this without using a loop.
Thanks for the help.
Edit: A, B below (abbreviated)
B = 735126
735154
735189
735217
735245
735280
735308
735336
735364
735399
735427
735462
735490
735518
735553
735581
735609
735644
A = 735126
735127
735128
735129
735130
735131
735132
735133
735134
735135
735136
735137
735138
735139
735140
735141
735142
735143
735144
735145
735146
735147
735148
735149
735150
735151
735152
735153
735154
735155
735156
735157
735158
735159
735160
735161
735162
735163
735164
735165
735166
735167
735168
735169
735170
735171
735172
735173
735174
735175
735176
735177
735178
735179
735180
735181
735182
735183
735184
735185
735186
735187
735188
735189
735190
735191
735192
735193
735194
735195
735196
735197
735198
735199
735200
735201
735202
735203
735204
735205
735206
735207
735208
735209
735210
735211
735212
735213
735214
735215
735216
735217
735218
735219
735220
735221
735222
735223
735224
735225
735226
735227
735228
735229
735230
735231
735232
735233
735234
735235
735236
735237
735238
735239
735240
735241
735242
735243
735244
735245
735246
735247
735248
735249
735250
735251
735252
735253
735254
735255
735256
735257
735258
735259
735260
735261
735262
735263
735264
735265
735266
735267
735268
735269
735270
735271
735272
735273
735274
735275
735276
735277
735278
735279
735280
735281
735282
735283
735284
735285
735286
735287
735288
735289
735290
735291
735292
735293
735294
735295
735296
735297
735298
735299
735300
735301
735302
735303
735304
735305
735306
735307
735308
735309
735310
735311
735312
735313
735314
735315
735316
735317
735318
735319
735320
735321
735322
735323
735324
735325
735326
735327
735328
735329
735330
735331
735332
735333
735334
735335
735336
735337
735338
735339
735340
735341
735342
735343
735344
735345
735346
735347
735348
735349
735350
735351
735352
735353
735354
735355
735356
735357
735358
735359
735360
735361
735362
735363
735364
735365
735366
735367
735368
735369
735370
735371
735372
735373
735374
735375
735376
735377
735378
735379
735380
735381
735382
735383
735384
735385
735386
735387
735388
735389
735390
735391
735392
735393
735394
735395
735396
735397
735398
735399
735400
735401
735402
735403
735404
735405
735406
735407
735408
735409
735410
735411
735412
735413
735414
735415
735416
735417
735418
735419
735420
735421
735422
735423
735424
735425
735426
735427
735428
735429
735430
735431
735432
735433
735434
735435
735436
735437
735438
735439
735440
735441
735442
735443
735444
735445
735446
735447
735448
735449
735450
735451
735452
735453
735454
735455
735456
735457
735458
735459
735460
735461
735462
735463
735464
735465
735466
735467
735468
735469
735470
735471
735472
735473
735474
735475
735476
735477
735478
735479
735480
735481
735482
735483
735484
735485
735486
735487
735488
735489
735490
735491
735492
735493
735494
735495
735496
735497
735498
735499
735500
735501
735502
735503
735504
735505
735506
735507
735508
735509
735510
735511
735512
735513
735514
735515
735516
735517
735518
735519
735520
735521
735522
735523
735524
735525
735526
735527
735528
735529
735530
735531
735532
735533
735534
735535
735536
735537
735538
735539
735540
735541
735542
735543
735544
735545
735546
735547
735548
735549
735550
735551
735552
735553
735554
735555
735556
735557
735558
735559
735560
735561
735562
735563
735564
735565
735566
735567
735568
735569
735570
735571
735572
735573
735574
735575
735576
735577
735578
735579
735580
735581
735582
735583
735584
735585
735586
735587
735588
735589
735590
735591
735592
735593
735594
735595
735596
735597
735598
735599
735600
735601
735602
735603
735604
735605
735606
735607
735608
735609
735610
735611
735612
Answer (using Excel) =
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
13
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
14
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
17
17
17
17
I'm assuming you want the last value of B such that all values up to that one satisfy the condition.
[~, result] = max(bsxfun(#gt, B(:), A(:).'), [], 1);
result = result-1;
result(~result) = numel(B);
Example:
>> A = [1 9 6 8 5];
>> B = [1 3 7 2];
>> [~, result] = max(bsxfun(#gt, B(:), A(:).'), [], 1);
>> result = result-1;
>> result(~result) = numel(B);
gives
A =
1 9 6 8 5
B =
1 3 7 2
result =
1 4 2 4 2
One approach -
[~,idx] = max(cumsum(bsxfun(#ge,A(:),B(:).'),2),[],2)
If you would like to remove cumsum -
[~,idx] = max(bsxfun(#ge,A(:),fliplr(B(:).')),[],2);
idx = numel(B) - idx + 1
Sample run -
>> A,B
A =
1 6 7 9 0 2 4 9 5
B =
0 2 8 4 5
>> idx
idx =
1
5
5
5
1
2
4
5
5

R create an array result of cutting (seq) of a data frame

I'm not comfortable with array manipulation (and english writing, sorry ..)
I've this data frame (aa):
aa<-data.frame(replicate(10,sample(0:17,30,rep=TRUE)))
> aa
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 17 7 9 2 3 7 17 0 15 1
2 12 5 10 10 8 17 13 7 2 2
3 14 14 7 7 16 1 13 0 14 6
4 12 10 10 15 7 2 7 11 4 0
5 1 9 5 5 8 15 15 11 8 17
6 8 0 9 6 7 11 9 12 4 17
7 17 1 17 5 11 8 16 0 2 15
8 10 7 15 6 17 3 0 16 16 15
9 8 3 14 13 16 5 15 8 14 10
10 11 13 15 3 17 13 13 4 11 12
11 9 13 0 7 4 13 15 1 2 0
12 1 3 17 13 10 4 12 5 4 15
13 5 8 9 8 0 6 14 13 0 8
14 17 11 10 4 15 10 7 1 1 7
15 2 0 16 7 13 10 13 3 10 7
16 5 5 15 7 0 17 10 14 11 4
17 10 17 9 11 0 9 9 17 0 4
18 12 8 8 16 11 4 10 16 4 7
19 5 7 13 12 17 17 17 17 6 8
20 13 17 1 2 0 1 8 4 17 17
21 15 15 5 13 6 16 5 5 14 13
22 12 4 5 1 2 7 17 2 9 9
23 12 5 13 16 6 6 15 2 13 10
24 8 6 12 4 5 11 7 12 14 10
25 5 11 15 1 17 3 8 10 4 4
26 3 10 8 14 1 13 16 1 16 11
27 10 2 14 11 6 8 13 3 8 10
28 14 5 7 12 8 14 16 9 16 14
29 5 17 16 17 12 1 3 8 2 0
30 5 17 12 2 8 9 3 1 14 15
I would like to create an array wich is the result of a cutting of dataframe (aa) like this (by seq of x elements, here for exemple 10): an array with 3 dimensions
, , 1
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 17 7 9 2 3 7 17 0 15 1
2 12 5 10 10 8 17 13 7 2 2
3 14 14 7 7 16 1 13 0 14 6
4 12 10 10 15 7 2 7 11 4 0
5 1 9 5 5 8 15 15 11 8 17
6 8 0 9 6 7 11 9 12 4 17
7 17 1 17 5 11 8 16 0 2 15
8 10 7 15 6 17 3 0 16 16 15
9 8 3 14 13 16 5 15 8 14 10
10 11 13 15 3 17 13 13 4 11 12
, , 2
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
11 9 13 0 7 4 13 15 1 2 0
12 1 3 17 13 10 4 12 5 4 15
13 5 8 9 8 0 6 14 13 0 8
14 17 11 10 4 15 10 7 1 1 7
15 2 0 16 7 13 10 13 3 10 7
16 5 5 15 7 0 17 10 14 11 4
17 10 17 9 11 0 9 9 17 0 4
18 12 8 8 16 11 4 10 16 4 7
19 5 7 13 12 17 17 17 17 6 8
20 13 17 1 2 0 1 8 4 17 17
etc...
i've already tried this...
aa_lag <-array(aa[1:10,],dim=c(dim(aa),3))
thank you so much for answer...
You can try
aa1 <- t(aa)
dim(aa1) <- c(10,10,3)
aa2 <- aperm(aa1, c(2,1,3))
Checking the results
m1 <- as.matrix(aa[1:10,])
dimnames(m1) <- NULL
identical(m1, aa2[,,1])
#[1] TRUE
Or using seq
lst <- lapply(seq(1,30, by=10), function(i) aa[i:(i+9),])
aa3 <- array(unlist(lst), dim=c(10,10,3))
identical(aa2, aa3)
#[1] TRUE
data
set.seed(24)
aa<-data.frame(replicate(10,sample(0:17,30,rep=TRUE)))

Resources