Copy certain number from one matrix to another - arrays

Im using matlab and I have a matrix
1 1
2 1
3 1
4 2
5 2
6 2
7 1
8 1
9 2
10 2
11 2
How can i copy matrix from second column but only certain number? the other number will be random either 1 or 2. Example
1 1 1 | | 1 1 1
2 1 1 | | 2 1 1
3 1 1 | | 3 1 1
4 2 2 | | 4 2 2
5 2 1 | OR | 5 2 2
6 2 1 | | 6 2 1
7 1 1 | | 7 1 1
8 1 1 | | 8 1 1
9 2 2 | | 9 2 2
10 2 2 | |10 2 1
11 2 1 | |11 2 1
If the third row of 2 become 1, the rest of the column will become 1. process repeat until it reach another set of 2

You can use the logical indexing and the function randi:
a = [1 1;
2 1;
3 1;
4 2;
5 2;
6 2;
7 1;
8 1;
9 2;
10 2;
11 2];
b = randi(2,length(a),1); %generation of random value ∈ [1,2]
b(a(:,2)==1) = 1; %if a(:,2) = 1 b = 1;
a = [a,b]

A= [1 1
2 1
1 1
4 2
5 2
6 2
7 1
8 1
9 2
10 2
11 2] ;
colLength = length (A(:,1)) ;
thridcol = randi (2,colLength,1)
A(:,3) = thridcol ;
flag = 1 ;
i = 1 ; ;
if ( sum (A(3,:) == 1) == length (A(2,:)))
while (flag && i < colLength)
A(3+i,3 ) = 1 ;
if (sum (A(3+i,:) == 2) == length (A(3+i,:)))
flag = 0 ;
end
i = i +1 ;
end
end

Related

Nested for-loop: error variable already defined

I have a nested loop in Stata with four levels of foreach statements. With this loop, I am trying to create a new variable named strata that ranges from 1 to 40.
foreach x in 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 28 29 30 31 32 33 34 35 36 37 38 39 40 {
foreach r in 1 2 3 4 5 {
foreach s in 1 2 {
foreach a in 1 2 3 4 {
gen strata= `x' if race==`r' & sex==`s' & age==`a'
}
}
}
}
I get an error :
"variable strata already defined"
Even with the error, the loop does assign strata = 1, but not the rest of the strata. All other cells are missing/empty.
Example data:
* Example generated by -dataex-. To install: ssc install dataex
clear
input byte(age sex race)
1 2 2
1 2 1
1 1 1
1 1 1
1 2 1
2 2 1
2 2 1
4 2 1
1 2 1
4 2 1
3 2 1
2 2 1
4 2 1
4 2 2
3 2 1
4 1 3
4 2 1
4 2 1
2 1 2
4 2 1
2 2 1
3 2 1
3 2 1
1 2 3
4 2 1
1 2 5
4 2 1
4 2 1
4 2 2
4 2 1
2 2 1
4 1 1
3 2 1
1 2 1
2 2 1
4 2 1
1 2 2
2 2 3
1 1 3
4 2 1
2 2 3
1 2 1
1 1 1
2 2 3
1 2 1
1 1 3
1 2 1
2 2 1
3 2 1
1 2 1
4 2 1
1 2 2
1 2 1
2 2 1
4 2 1
4 2 1
1 2 1
1 2 1
4 2 1
2 2 1
4 2 1
1 2 1
1 1 3
2 2 1
1 1 1
4 1 1
3 2 1
2 2 1
1 2 1
1 1 1
2 2 3
4 2 2
2 2 1
2 2 1
3 2 1
2 2 2
3 2 1
2 1 1
1 1 1
3 2 1
1 2 3
4 2 1
4 2 1
2 2 1
1 2 1
1 1 1
3 2 1
4 2 1
2 2 3
1 2 3
4 2 1
3 2 1
2 2 1
4 2 1
3 2 1
2 1 1
1 2 1
2 2 1
2 2 3
1 1 1
end
label values sex sex
label def sex 1 "male (1)", modify
label def sex 2 "female (2)", modify
label values race race
label def race 1 "non-Hispanic white (1)", modify
label def race 2 "black (2)", modify
label def race 3 "AAPI/other (3)", modify
label def race 5 "Hispanic (5)", modify
generate is for generating new variables. The second time your code reaches a generate statement, the code fails for the reason given.
One answer is that you need to generate your variable outside the loops and then replace inside.
For other reasons your code can be rewritten in stages.
First, integer sequences can be more easily and efficiently specified with forvalues, which can be abbreviated: I tend to write forval.
gen strata = .
forval x = 1/40 {
forval r = 1/5 {
forval s = 1/2 {
forval a = 1/4 {
replace strata = `x' if race==`r' & sex==`s' & age==`a'
}
}
}
}
Second, the code is flawed any way. Everything ends up as 40!
Third, you can do allocations much more directly, say by
gen strata = 8 * (race - 1) + 4 * (sex - 1) + age
This is a self-contained reproducible demonstration:
clear
set obs 5
gen race = _n
expand 2
bysort race : gen sex = _n
expand 4
bysort race sex : gen age = _n
gen strata = 8 * (race - 1) + 4 * (sex - 1) + age
isid strata
Clearly you can and should vary the recipe for a different preferred scheme.

How do we make arrays in awk?

{
k = 0
x = 0
fracon = (10/2)+1
{
for (j = 1; j <= 1100 ; j++)
{
if (j <= fracon)
scal[j]= j-x
else
k= k + 1
scal[j]= j - (2*k)
{
if (scal[j] == 1)
fracon= fracon+11
{
if (j % 11 == 0)
x=x+11
k=k+0.5
}
}
}
}
}
That's all. I used the above code to generate the following array. It works in Matlab, but it does not work in awk.
array= [1 2 3 4 5 6 5 4 3 2 1 1 2 3 4 5 6]
here is another way of generating the same sequence
$ awk 'BEGIN{for(i=0;i<=20;i++) {k=i%11+1; printf "%s ", (k<7?k:12-k)}; print ""}'
1 2 3 4 5 6 5 4 3 2 1 1 2 3 4 5 6 5 4 3 2
not sure what you want is just repeated on a 11 element cycle or not; difficult to say based on limited sample.
or without awk
$ yes $({ seq 6; seq 5 -1 1; } | paste -sd' ') | head -100 | paste -sd' '
1 2 3 4 5 6 5 4 3 2 1 1 2 3 4 5 6 5 4 3 2 1 ...
with square brackets
$ awk 'BEGIN{printf "[";
for(i=0;i<=1100;i++) {k=i%11+1; printf "%s ", (k<7?k:12-k)};
printf "]\n"}'
[1 2 3 4 5 6 5 4 3 2 1 1 2 3 4 5 6 ... 5 4 3 2 1 ]
Stuffing these values into a large array is not optimal, you can write a function to return the indexed value easily
$ awk 'function k(i,_i) {_i=i%11+1; return _i<7?_i:12-_i}
BEGIN{for(i=0;i<=25;i++) print k(i)}'
in the real code, you'll use k(i) instead of printing. Note the array index starts from 0.
N.B. the _i is a local variable in the awk function; you don't need to use in the call syntax.

Print a console "picture" using recursion

I'm having some trouble printing the following picture.
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 (16 times)
2 2 2 2 2 2 2 2 2 2 2 2 (12 times)
3 3 3 3 3 3 3 3 (8 times)
4 4 4 4 (4 times)
3 3 3 3 3 3 3 3 (8 times)
2 2 2 2 2 2 2 2 2 2 2 2 (12 times)
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 (16 times)
It's easy for me to implement an iterative algorithm, but I have to use recursion. I've written the following code (C++) that seems to do the job.
void print(int n, int current)
{
int offset = (n / 2) * (current - 1);
int i;
for (i = 0; i < offset; i++)
printf(" ");
for (i = 1; i <= (n - current + 1) * n; i++)
printf("%i ", current);
printf("\n");
}
void picture(int n, int current)
{
if (current < n) {
print(n, current);
picture(n, current + 1);
print(n, current);
}
else
if (current == n)
print(n, current);
}
int main()
{
int n;
input: printf("Enter n --> ");
scanf_s("%i", &n);
if ((n < 1) || (n > 9) || (n % 2 == 1)) {
printf("ERROR: n must be an even decimal digit!\n");
goto input;
}
picture(n, 1);
return 0;
}
I wonder whether there is a simpler way to write the recursive function here.
Update: I've tried to identify the recursion in a much simpler problem of printing the "pyramid":
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
The function pyram receives two parameters: the maximum number n (5 in our case) and the current number k. k is printed k times, then pyram is called with the parameters n and k + 1. This happens only when k <= n.
void pyram(int n, int k)
{
if (k <= n) {
for (int i = 1; i <= k; i++)
printf("%i ", k);
printf("\n");
pyram(n, k + 1);
}
}
I've written my solution to the original problem in a similar manner.
You can use static variables in the recursive function. In this case the function declaration will look simpler and you will not need an auxiliary function.
For example
#include <stdio.h>
void display_pattern( unsigned int n )
{
const unsigned int FACTOR = 4;
static unsigned int value = 1;
static int indent = 1;
if ( n )
{
printf( "%*u", indent, value );
for ( unsigned int i = 1; i < FACTOR * n; i++ ) printf( " %u", value );
putchar( '\n' );
indent += FACTOR;
++value;
display_pattern( --n );
indent -= FACTOR;
--value;
}
if ( n++ )
{
printf( "%*u", indent, value );
for ( unsigned int i = 1; i < FACTOR * n; i++ ) printf( " %u", value );
putchar( '\n' );
}
}
int main(void)
{
const unsigned int N = 10;
while ( 1 )
{
printf( "Enter a non-negative number less than %u (0 - exit): ", N );
unsigned int n;
if ( scanf( "%u", &n ) != 1 || n == 0 ) break;
if ( !( n < N ) ) n = N - 1;
putchar( '\n' );
display_pattern( n );
putchar( '\n' );
}
return 0;
}
The program output can look like
Enter a non-negative number less than 10 (0 - exit): 10
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 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
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
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
7 7 7 7 7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
9 9 9 9
8 8 8 8 8 8 8 8
7 7 7 7 7 7 7 7 7 7 7 7
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
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
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
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 1 1 1 1 1 1 1 1
Enter a non-negative number less than 10 (0 - exit): 4
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
3 3 3 3 3 3 3 3
4 4 4 4
3 3 3 3 3 3 3 3
2 2 2 2 2 2 2 2 2 2 2 2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Enter a non-negative number less than 10 (0 - exit): 0
As for the function pyram then it can look like
void display_triangle( unsigned int n )
{
if ( n )
{
display_triangle( n - 1 );
for ( unsigned int i = 0; i < n; i++ ) printf( "%u ", n );
putchar( '\n' );
}
}

Complete set of combinations combining 3 set

I need to generate the complete set of combinations obtained combining three different subset:
Set 1: choosing any 4 numbers from a vector of 13 elements.
Set 2: choosing any 2 numbers from a vector of 3 elements.
Set 3: choosing any 2 numbers from a vector of 9 elements.
Example: sample 3 from vector of 4 (H=3 and L=4) for the Set A, H=2 L=3 for the Set B and H=2 L=4 for the Set B:
4 4 4
3 4 4
3 3 4
3 3 3
2 4 4
2 3 4
2 3 3
2 2 4
Set A = 2 2 3
2 2 2
1 4 4
1 3 4
1 3 3
1 2 4
1 2 3
1 2 2
1 1 4
1 1 3
1 1 2
1 1 1
3 3
2 3
Set B = 2 2
1 3
1 2
1 1
4 4
3 4
3 3
2 4
Set C = 2 3
2 2
1 4
1 3
1 2
1 1
[Set A] = [20 x 3], [Set B] = [6 x 2], [Set C] = [10 x 2]. Then I need to obtain all possible combinations from these three sets: AllComb = [Set A] x [Set B] x [Set C] = [1200 x 8]. The AllComb matrix will be like this:
4 4 4 | 3 3 | 4 4
4 4 4 | 3 3 | 3 4
4 4 4 | 3 3 | 3 3
4 4 4 | 3 3 | 2 4
4 4 4 | 3 3 | 2 3
4 4 4 | 3 3 | 2 2
4 4 4 | 3 3 | 1 4
4 4 4 | 3 3 | 1 3
4 4 4 | 3 3 | 1 2
4 4 4 | 3 3 | 1 1
4 4 4 | 2 3 | 4 4
4 4 4 | 2 3 | 3 4
4 4 4 | 2 3 | 3 3
4 4 4 | 2 3 | 2 4
4 4 4 | 2 3 | 2 3
.
.
.
1 1 1 | 1 1 | 1 1
Unfortunately I can not use the same number for the sets since I need to substitute the numbers like that:
For Set A: 1 = 10, 2 = 25, 3 = 30 and 4 = 45
For Set B: 1 = 5, 2 = 20 and 3 = 35
For Set C: 1 = 10, 2 = 20, 3 = 30 and 4 = 50
Any ideas? Real case sets will often lead to an AllComb matrix ~[491 400 x 8] so vectorized solutions will be gladly accepted.
Note: Each set is obtained with the following code:
a = combnk(1:H+L-1, H);
b = cumsum([a(:,1) diff(a,[],2) - 1],2);
What is H and L?
H are the hoppers of a MultiheadWeigher (MHW) machines. I have a MHW with H=8 and I need to deliver in each of these hoppers some materials. If I need to deliver just one type of material all possibile combinations are (L+H-1)!/(H!(L-1)!) and i compute them with the code write above (a and b). Now, suppose to have 3 different product then we have 4 hoppers for product A, 2 for B and 2 for C. Product A in the first 4 hoppers can assume values 10:10:130, Product B 10:10:30 and c 10:10:90. Then the number of steps are for A L=13, B L=3 and C L=9
You basically need to find
Combinations with repetition for each set;
"Multi-variations" (I don't know the correct name for this) of the results of stage 1.
Both stages can be solved with more or less the same logic, taken from here.
%// Stage 1, set A
LA = 4;
HA = 3;
SetA = cell(1,HA);
[SetA{:}] = ndgrid(1:LA);
SetA = cat(HA+1, SetA{:});
SetA = reshape(SetA,[],HA);
SetA = unique(sort(SetA(:,1:HA),2),'rows');
%// Stage 1, set B
LB = 3;
HB = 2;
SetB = cell(1,HB);
[SetB{:}] = ndgrid(1:LB);
SetB = cat(HB+1, SetB{:});
SetB = reshape(SetB,[],HB);
SetB = unique(sort(SetB(:,1:HB),2),'rows');
%// Stage 1, set C
LC = 4;
HC = 2;
SetC = cell(1,HC);
[SetC{:}] = ndgrid(1:LC);
SetC = cat(HC+1, SetC{:});
SetC = reshape(SetC,[],HC);
SetC = unique(sort(SetC(:,1:HC),2),'rows');
%// Stage 2
L = 3; %// number of sets
result = cell(1,L);
[result{:}] = ndgrid(1:size(SetA,1),1:size(SetB,1),1:size(SetC,1));
result = cat(L+1, result{:});
result = reshape(result,[],L);
result = [ SetA(result(:,1),:) SetB(result(:,2),:) SetC(result(:,3),:) ];
result = flipud(sortrows(result)); %// put into desired order
This gives
result =
4 4 4 3 3 4 4
4 4 4 3 3 3 4
4 4 4 3 3 3 3
4 4 4 3 3 2 4
4 4 4 3 3 2 3
4 4 4 3 3 2 2
4 4 4 3 3 1 4
4 4 4 3 3 1 3
4 4 4 3 3 1 2
4 4 4 3 3 1 1
4 4 4 2 3 4 4
4 4 4 2 3 3 4
4 4 4 2 3 3 3
4 4 4 2 3 2 4
4 4 4 2 3 2 3
4 4 4 2 3 2 2
4 4 4 2 3 1 4
4 4 4 2 3 1 3
4 4 4 2 3 1 2
...
I guess this could be further optimized but this generates you AllComb:
H=3;
L=4;
a = combnk(1:H+L-1, H);
b = cumsum([a(:,1) diff(a,[],2) - 1],2);
H=2;
L=3;
c = combnk(1:H+L-1, H);
d = cumsum([c(:,1) diff(c,[],2) - 1],2);
H=2;
L=4;
e = combnk(1:H+L-1, H);
f = cumsum([e(:,1) diff(e,[],2) - 1],2);
u=[];
for k=1:10
u=vertcat(u,d);
end
u=sortrows(u,[1 2]);
v=[];
for k=1:6
v= vertcat(v,f);
end
w= [u,v];
v=[];
for k=1:20
v= vertcat(v,w);
end
u=[];
for k=1:60
u = vertcat(u,b);
end
u=sortrows(u,[1 2 3]);
AllComb= [u,v];
Here b,d and f are your 3 sets. Then i loop over the numbers of permutation in d and f and replicate them so that all possibilities are constructed. One of them is sorted and then i write them in a new matrix w. THis process is repeated with Set A (b) and this new constructed matrix. Resulting in the end in AllComb.

how to vectorize the following for loop?

can any one help me to Vectorized this loop.
i have large Matrix and i want to replace all the pixel values whose length is less then some threshold Value For simplicity lets say
a = randi([1 5],10,10);
for i = 1:length(a)
someMat=a(a==i);
if length(someMat)<20
a(a==i)=0;
end
end
but its killing me.
Example:
a = randi([1 5],10,10)
a =
5 2 1 5 5 5 2 2 3 2
3 3 5 4 4 4 3 1 1 5
5 1 3 5 3 3 4 1 3 1
3 1 5 3 2 5 1 1 5 1
1 1 4 3 4 3 4 4 5 1
1 4 3 5 1 1 2 2 2 1
3 3 5 2 4 1 1 3 2 4
4 1 5 3 4 5 3 4 3 3
5 3 5 5 4 3 1 3 4 1
4 1 1 3 5 5 1 3 3 5
Result for Thresold 20
5 0 1 5 5 5 0 0 3 0
3 3 5 0 0 0 3 1 1 5
5 1 3 5 3 3 0 1 3 1
3 1 5 3 0 5 1 1 5 1
1 1 0 3 0 3 0 0 5 1
1 0 3 5 1 1 0 0 0 1
3 3 5 0 0 1 1 3 0 0
0 1 5 3 0 5 3 0 3 3
5 3 5 5 0 3 1 3 0 1
0 1 1 3 5 5 1 3 3 5
length of pixel 4 was 17
length of pixel 2 was 10
i try it by some thing like
[nVal Index] = histc(a(:),unique(a)); %
nVal(nVal>20) = 1; % just some threshold value and assigning by some Number may be zero as well
But I dont Know how to replace the Index Values of the corresponding Pixal and apply reshape to get it in original form. Here Even i am not sure that i will get the same Matrix With Reshape . Please Help me.....
thanks
I think this does what you want:
threshold_length = 20;
replace_value = 0;
u = unique(a); %// values of a
h = histc(a(:), u); %// count for each value
r = u(h<threshold_length); %// values to be removed
a(ismember(a,r)) = replace_value; %// remove those values
I see #LuisMendo arrived at mostly the same solution quicker than I did, but an alternative to using ismember is to use more of what unique gives you:
threshold = 20;
[vals, ~, ix] = unique(a); % capture the values and their indices
counts = histc(a(:), vals); % count the occurrences of each value
vals(counts<threshold) = 0; % zero the values that aren't common enough
a(:) = vals(ix); % recreate the matrix with updated values

Resources