I would like to compute a formula, which is the survival rate, in my case I will call it by Z variable. I was thinking about use a macro but i cant get a easy way to do it. In the table below i have an example what it is pretended.
the propose is to perform the Z calculation by id.
So X(i,j) variable is the probability of default of id i in id_time j, where i = 1,..,3 and j = 1,..,4
Y(i,j) = 1 - x(i,j) always.
Z(i,j) = Y(i,j-1) * Z(i,j-1) except when j = 1, where Z(i,1) = 1 = 100%.
If you guys need some more details just let me know.
Here it is the example:
id id_time x y z
1 1 0,010 0,990 1
1 2 0,015 0,985 0,990
1 3 0,020 0,980 0,975
1 4 0,025 0,975 0,956
2 1 0,010 0,990 1
2 2 0,015 0,985 0,990
2 3 0,020 0,980 0,975
2 4 0,020 0,980 0,956
3 1 0,005 0,995 1
3 2 0,010 0,990 0,995
3 3 0,020 0,980 0,985
3 4 0,030 0,970 0,965
I do it as your formula.
data test;
format x y 12.3;
input id: id_time: x: comma9. y: comma9.;
x = x * 0.001;
y = y * 0.001;
cards;
1 1 0,010 0,990
1 2 0,015 0,985
1 3 0,020 0,980
1 4 0,025 0,975
2 1 0,010 0,990
2 2 0,015 0,985
2 3 0,020 0,980
2 4 0,020 0,980
3 1 0,005 0,995
3 2 0,010 0,990
3 3 0,020 0,980
3 4 0,030 0,970
;
run;
data _null_;
retain Z;
set test;
by id notsorted;
LagY = Lag(y);
if first.id then LagY = .;
if first.id then Z = 1;
if not first.id then Z = round(LagY * Z,0.001);
put (id id_time x y z)(=);
run;
Output:
id=1 id_time=1 x=0.010 y=0.990 Z=1
id=1 id_time=2 x=0.015 y=0.985 Z=0.99
id=1 id_time=3 x=0.020 y=0.980 Z=0.975
id=1 id_time=4 x=0.025 y=0.975 Z=0.956
id=2 id_time=1 x=0.010 y=0.990 Z=1
id=2 id_time=2 x=0.015 y=0.985 Z=0.99
id=2 id_time=3 x=0.020 y=0.980 Z=0.975
id=2 id_time=4 x=0.020 y=0.980 Z=0.956
id=3 id_time=1 x=0.005 y=0.995 Z=1
id=3 id_time=2 x=0.010 y=0.990 Z=0.995
id=3 id_time=3 x=0.020 y=0.980 Z=0.985
id=3 id_time=4 x=0.030 y=0.970 Z=0.965
Related
Currently I have this function in MATLAB
function [ y ] = pyramid( x )
%PYRAMID Returns a "pyramid"-shapped matrix.
y = zeros(x); % Creates an empty matrix of x by x.
rings = ceil(x/2); % Compute number of "rings".
for n = 1:rings
% Take the first and last row of the ring and set values to n.
y([n,x-n+1],n:x-n+1) = n*ones(2,x-2*(n-1));
% Take the first and last column of the ring and set values to n.
y(n:x-n+1,[n,x-n+1]) = n*ones(x-2*(n-1),2);
end
end
Which produces the following output:
piramide(4)
ans =
1 1 1 1
1 2 2 1
1 2 2 1
1 1 1 1
piramide(5)
ans =
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
piramide(6)
ans =
1 1 1 1 1 1
1 2 2 2 2 1
1 2 3 3 2 1
1 2 3 3 2 1
1 2 2 2 2 1
1 1 1 1 1 1
Is there a way to achive the same result without using a for-loop ?
If you have the Image Processing Toolbox you can use bwdist:
function y = pyramid(x)
m([1 x], 1:x) = 1;
m(1:x, [1 x]) = 1;
y = bwdist(m,'chessboard')+1;
end
Other solution using min:
pyramid = #(x) min(min((1:x),(1:x).'), min((x:-1:1),(x:-1:1).'));
Please allow me to post this admin:
ok so this is my problem, i want to generate all combination of a, and b, for example 1 and 2, having a combinations of (1,2), (2,1),(-1,2), and (2,-1), so 4 combination, but i want only one combination as representative of all 4 combination to be display in output for example only (1,2). so this is my draft code:
fprintf(' a b z \n _ _ _ \n');
for a= -1:3
for b=-1:3
z=a^2 + b^2
end
end
ctr=1;
i(:,3) %the position of z in array
for x =1:length(z) %the length of z array
if z = i(1,1)
ctr = ctr +1;
else
fprintf(' %d %d %d\n',a,b,z);
end
end
so this the output i want:
a b z no. of repetitions
1 1 2 4
1 0 1 4
1 2 5 4
1 3 10 4
0 2 4 2
0 3 9 2
2 2 8 1
2 3 13 2
3 3 18 1
0 0 0 1
no. of repetition means how many possible combination of a and b can generate
in=-1:3
%calculate z
[a,b]=meshgrid(in);
z=a.^2+b.^2;
%sort absolute values ascending, which allows to use unique
ac=sort(abs([a(:) b(:)]),2);
%use unique to identify duplicates
[f,g,h]=unique(ac,'rows');
%count
cnt=histc(h,1:max(h));
disp([a(g),b(g),z(g),cnt])
The output is:
0 0 0 1
1 0 1 4
2 0 4 2
3 0 9 2
1 1 2 4
2 1 5 4
3 1 10 4
2 2 8 1
3 2 13 2
3 3 18 1
I have random matrix with arbitrary dimensions and I want to assign a color for each value (randomly or not) and plot the matrix with numbers like,
So far I've done this,
m = 12;
n = 8;
A = randi(5,[m n]);
Arot = flipud(A);
pcolor(Arot);figure(gcf);
for i = 1 : n -1
for j = 1 : m -1
text(i + .5 , j + .5 ,num2str(Arot(j,i)),'FontSize',18);
end
end
which gives me this,
for
A =
4 4 4 1 2 1 4 2
5 2 2 3 2 1 1 2
1 2 1 4 1 2 5 5
1 3 5 3 1 4 1 3
3 4 4 4 3 3 3 4
2 5 2 2 1 1 2 4
1 3 1 3 5 5 2 4
5 1 2 4 1 4 1 2
2 4 5 5 1 3 5 2
4 2 2 3 4 3 3 4
3 5 3 2 4 3 3 1
1 4 5 3 2 4 3 5
but as you can see I've lost first row and last column of A.
Actually the problem starts bu using pcolor, which gives an (m-1)x(n-1) plot for mxn input.
Any suggestions?
Thanks,
Using imagesc instead of pcolor solves the problem. It also brings some other benefits:
Avoids the need for flipud;
The coordinates of the text objects become integer values;
Axes are automatically set to "matrix" mode, with the origin in the upper right corner.
Code:
m = 8;
n = 6;
A = randi(5,[m n]);
imagesc(A);
for ii = 1:n
for jj = 1:m
text(ii, jj, num2str(A(jj,ii)), 'FontSize', 18);
end
end
For
A =
4 5 4 2 4 4
5 4 3 4 4 2
5 4 1 1 1 3
4 3 5 2 5 4
1 2 2 2 5 3
1 5 2 5 1 3
4 3 1 3 3 1
3 1 2 4 2 3
this produces
I just padded the matrix prior to pcolor and I think it's the effect you wanted. The reason it works comes from the help doc for pcolor, which states that
In the default shading mode, 'faceted', each cell has a constant color
and the last row and column of C are not used.
m = 12;
n = 8;
A = randi(5,[m n]);
Arot = flipud(A);
Arot = [ Arot; Arot(end,:) ];
Arot = [ Arot, Arot(:,end) ];
pcolor(Arot);figure(gcf);
for i = 1 : n
for j = 1 : m
text(i + .5 , j + .5 ,num2str(Arot(j,i)),'FontSize',18);
end
end
This is a similar request to my post at Iterate one vector through another in Matlab
I am using Luis' suggestion with the following code:
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
This produces a good result for C as a 1024x10 matrix with all possible permutations of 1 and 2 to a length of 10 columns. What I want to do is remove any rows that are not in increasing order. For example now I get:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 1 2 2
All are valid except for the third row since it goes from 2 to back to 1.
I have code to get the desired result, but it is very slow and inefficient.
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
min=0;
for row=1:size(C,1)
for col=1:size(C,2)
if(C(row,col)>min)
min=C(row,col);
elseif(C(row,col)<min)
C(row,:)=0;
continue;
end
end
min=0;
end
C = C(any(C,2),:); %remove all zero rows
The desired output is now:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 2
1 1 1 1 1 1 1 2 2 2
1 1 1 1 1 1 2 2 2 2
1 1 1 1 1 2 2 2 2 2
1 1 1 1 2 2 2 2 2 2
1 1 1 2 2 2 2 2 2 2
1 1 2 2 2 2 2 2 2 2
1 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
Any ideas on how to optimize my code so I do not need to use nested loops?
The super-simple but not-quite-so-obvious solution via a couple of row-wise operations:
d = diff(C, [], 2);
m = min(d, [], 2);
C = C(m>=0, :);
Of course, in this particular example it would be far easier to just generate the resulting matrix directly:
C = flipud(triu(ones(s+1,s).*(max(A)-min(A))) + min(A));
but I assume you're also interested in less trivial values of A ;)
I have a 32 x 3 matrix as follows:
A =
[ 1 1 1;
1 1 2;
1 1 3;
1 1 4;
1 1 5;
1 1 6;
1 1 7;
1 1 8;
1 2 1;
1 2 2;
1 2 3;
1 2 4;
1 2 5;
1 2 6;
1 2 7;
1 2 8;
2 1 1;
2 1 2;
2 1 3;
2 1 4;
2 1 5;
2 1 6;
2 1 7;
2 1 8;
2 2 1;
2 2 2;
2 2 3;
2 2 4;
2 2 5;
2 2 6;
2 2 7;
2 2 8]
What I need to do is randomise the order of the rows, while keeping the row values together, however, this needs to be constrained such that for A(:, 4), every 8 rows contain only the numbers 1 - 8. So for example, you could have something like:
A(1:8, :) =
[ 1 2 4;
1 1 5;
2 1 6;
1 1 8;
2 2 1;
2 1 2;
2 1 7;
1 1 3]
The occurrence of 1 and 2 in the first two columns needs to be random, 1 - 8 needs to be randomised for every 8 values of the third column. Initially I tried to use the function randswap within a loop with an added constraint, but this has only led to an infinite loop. Also important that the rows stay together as the 1s and 2s in the first two columns need to appear alongside the last column an equal number of times. Someone suggested the following, but it doesn't quite work out..
m = size(A,1);
n = 1:8;
out = 1;
i2 = 1;
while ~all(ismember(1:8,out)) && i2 < 100
i1 = randperm(m);
out = A(i1(n),:);
i2 = i2 + 1;
end
If all you need is to get one set of 8 rows out of A, you can construct the result like this:
out = [randi([1,2],[8,2]),randperm(8)']
out =
2 1 5
2 1 2
2 1 1
1 2 7
2 2 6
1 1 8
2 2 3
1 1 4
If you need to randomize all of A, you can do the following:
%# calculate index for the 1's and 2's
r = rand(8,4);
[~,idx12] = sort(r,2);
%# calculate index for the 1's through 8's
[~,idx8] = sort(r,1);
%# use idx8 to shuffle idx12
idx8into12 = bsxfun(#plus,idx8,[0 8 16 24]);
%# now we can construct the output matrix
B = [1 1;1 2;2 1;2 2];
out = [B(idx12(idx8into12),:),idx8(:)];
out =
1 1 7
1 2 3
1 2 1
2 1 8
2 1 5
2 2 4
2 2 2
2 1 6
1 1 3
1 2 7
1 1 1
1 2 8
1 2 4
1 1 5
2 2 6
2 1 2
1 1 8
2 1 7
1 2 5
2 1 1
1 2 6
2 1 3
1 1 2
1 1 4
2 1 4
2 2 7
2 2 8
2 2 3
1 2 2
1 1 6
2 2 5
2 2 1
If you do unique(out,'rows'), you'll see that there are indeed 32 unique rows. Every 8 rows in out have the numbers 1 through 8 in the third column.