/* sample from a mixture distribution */
%let N = 5000;
data States(drop=i);
call streaminit(12345);
array prob [2] _temporary_ (0.7 0.3);
do i = 1 to &N;
type = rand("Table", of prob[*]);
if type=1 then Return = rand("Normal", 0, 3); /* state 1 */
else Return = rand("Normal", 5, 10); /* steta 2 */
output;
end;
run;
proc means data = States mean var std maxdec=5 missing n nmiss ; *Taking mean and std of return in state 1 and 2;
var return;
class type;
output out=Statesmu mean=mu var=var std=std;
title 'Mean, Variance and Standard Deviation of the return in 2 states';
run;
data work.States; *Getting A,B,C,D from the table;
set work.States;
Pi = constant("pi");
Res1 = Return + 0.06780;
Res2 = Return - 5.21819;
UncDen = (0.7/(sqrt(2*3.141592657)*2.98245))*(exp(((-0.5)*((Res1)/2.98245))**2)) + (0.3/(sqrt(2*3.141592657)*9.96359))*(exp(((-0.5)*((Res2)/9.96359))**2));
ConA = (1/(sqrt(2*3.141592657)*2.98245))*(exp(((-0.5)*((Res1)/2.98245))**2));
ConB = (1/(sqrt(2*3.141592657)*9.96359))*(exp(((-0.5)*((Res2)/9.96359))**2));
pi1 = 3400/5000;
pi2 = 1600/5000;
ConprobA = ConA*pi1;
ConprobB = ConB*pi2;
PrC = ConprobA/UncDen;
PrD = ConprobB/UncDen;
Run;
Hi, I have a basic question with matrix calculation.
If: I have 15 columns variables say 5000 by 15
Need: take only column 15 and inverse it, and then multiply with a 2 by 1 vector.
Can anyone give some hint how to do that?
I don't know how to take a column and treat it as a vector or combine two columns and treat it as a vector.
Example: As shown in the example, Iet's say I need to combine ConprobA and ConprobB as a vector and then multiply with a 2 by 1 vector.
Any suggestion would be appreciated. Thank you.
In the DATA step, double vertical bars (||) is the operator for string concatenation. So the following DATA step creates a CHARACTER variable z, which is the string-wise concatenation of x and y:
data a;
x=1.23; y=4.56; z = x || y;
put z;
run;
In contrast, the horizontal concatenation operator (||) in SAS/IML concatenates two vectors into a matrix that has two columns. So i n PROC IML the same statement results in a 1x2 vector:
proc iml;
x=1.23; y=4.56; z = x || y;
print z;
run;
SAS/IML Software and Matrix Computations
see
https://goo.gl/w8IrLt
https://communities.sas.com/t5/SAS-IML-Software-and-Matrix/Convert-a-column-to-a-vector/m-p/348302
"I don't know how to take a column and treat it as a vector or combine two columns and treat it as a vector.
Example: As shown in the example, Iet's say I need to combine ConprobA and ConprobB as
a vector and then multiply with a 2 by 1 vector."
You can use IML directly for this problem, probably simpler.
This R solution can be converted to IML easily or
you can use the IML interface to R.
The free version of WPS does not limit the size of the SAS dataset
created by 'proc r'.
HAVE1
=====
Up to 40 obs WORK.STATES total obs=10
Obs CONPROBA CONPROBB
1 0.09303 0.013450
2 0.09269 0.013473
3 0.28243 0.018018
4 0.14858 0.016055
5 0.10607 0.013096
and
HAVE2
=====
obs sum2col
1 1
2 1
WANT
Obs CONPROBA CONPROBB SUM2COL RES
1 0.09303 0.013450 X 1 0.1064845
2 0.09269 0.013473 1 0.1061672
3 0.28243 0.018018 0.3004481
4 0.14858 0.016055 0.1646374
5 0.10607 0.013096 0.1191660
WORKING CODE
===========
res<-crossprod(t(have1), have2);
* _ _ _
_ __ ___ __ _| | _____ __| | __ _| |_ __ _
| '_ ` _ \ / _` | |/ / _ \_____ / _` |/ _` | __/ _` |
| | | | | | (_| | < __/_____| (_| | (_| | || (_| |
|_| |_| |_|\__,_|_|\_\___| \__,_|\__,_|\__\__,_|
;
libname sd1 "d:/sd1";
options validvarname=upcase;
/* sample from a mixture distribution */
%let N = 5000;
data States(drop=i);
call streaminit(12345);
array prob [2] _temporary_ (0.7 0.3);
do i = 1 to &N;
type = rand("Table", of prob[*]);
if type=1 then Return = rand("Normal", 0, 3); /* state 1 */
else Return = rand("Normal", 5, 10); /* steta 2 */
output;
end;
run;
proc means data = States mean var std maxdec=5 missing n nmiss ;
*Taking mean and std of return in state 1 and 2;
var return;
class type;
output out=Statesmu mean=mu var=var std=std;
title 'Mean, Variance and Standard Deviation of the return in 2 states';
run;
data sd1.have1(keep=CONPROBA CONPROBB);
*Getting A,B,C,D from the table;
set work.States(obs=10);
Pi = constant("pi");
Res1 = Return + 0.06780;
Res2 = Return - 5.21819;
UncDen = (0.7/(sqrt(2*3.141592657)*2.98245))*(exp(((-0.5)*((Res1)/2.98245))**2)) +
(0.3/(sqrt(2*3.141592657)*9.96359))*(exp(((-0.5)*((Res2)/9.96359))**2));
ConA = (1/(sqrt(2*3.141592657)*2.98245))*(exp(((-0.5)*((Res1)/2.98245))**2));
ConB = (1/(sqrt(2*3.141592657)*9.96359))*(exp(((-0.5)*((Res2)/9.96359))**2));
pi1 = 3400/5000;
pi2 = 1600/5000;
ConprobA = ConA*pi1;
ConprobB = ConB*pi2;
PrC = ConprobA/UncDen;
PrD = ConprobB/UncDen;
Run;
data sd1.have2;
sum2col=1;
output;
sum2col=1;
output;
run;quit;
* _ _ _
___ ___ | |_ _| |_(_) ___ _ __
/ __|/ _ \| | | | | __| |/ _ \| '_ \
\__ \ (_) | | |_| | |_| | (_) | | | |
|___/\___/|_|\__,_|\__|_|\___/|_| |_|
;
%utl_submit_wps64('
libname sd1 "d:/sd1";
options set=R_HOME "C:/Program Files/R/R-3.3.2";
libname wrk "%sysfunc(pathname(work))";
proc r;
submit;
source("c:/Program Files/R/R-3.3.2/etc/Rprofile.site",echo=T);
library(haven);
have1<-as.matrix(read_sas("d:/sd1/have1.sas7bdat"));
have2<-as.matrix(read_sas("d:/sd1/have2.sas7bdat"));
res<-crossprod(t(have1), have2);
endsubmit;
import r=res data=wrk.reswps;
run;quit;
');
proc print data=reswps;
run;quit;
Obs V1
1 0.10648
2 0.10617
3 0.30045
4 0.16464
5 0.11917
6 0.10472
7 0.10631
8 0.12975
9 0.11549
10 1.45924
thank you, I need study your reply later to make them work in my sas.
There are many ways to multiply in the SAS/IML matrix.
I don't understand some of your requests. What do you mean by "take only column 15 and inverse it"? (by the way, your example only has 14 columns...)
Also, when you say you want to multiply a column vector by a 2x1 vector, what do you mean? If v is a 2x1 vector, do you want the product x*v` or something else? Please provide an example with numbers for N=5.
The only lines in the DATA step that look similar to your request are the statements
ConprobA = ConA*pi1;
ConprobB = ConB*pi2;
Here are some IML statements that might give you some feeling for how to extract columns and multiply columns together:
proc iml;
use States;
read all var _NUM_ into X[colname=varNames];
close States;
print varNames;
/* general exaples of extracting columns */
A = X[ ,14]; /* get column 14 */
B = X[ ,13:14]; /* get columns 13-14 */
Y = X[ , {"ConprobA" "ConprobB"}]; /* get the 2 columns */
p = {0.68, 0.32}; /* 2 x 1 vector */
LinComb = Y * v; /* form linear combination of columns of Y */
print (LinComb[1:5,]); /* print only 5 rows */
Con = Y # v`; /* elementwise multiplication */
print (Con[1:5,])[colname={"ConA" "ConB"}];
If you are looking for a good overview of basic matrix multiplication and manipulations in SAS/IML, I recommend "Getting Started with the SAS/IML Language"
Thank you for replying and sorry for the confusion.
I combined column 13 and 14 yesterday and got the conlumn 15 like that:
P = ConprobA || ConprobB;
Here is the sample of 5 for what I mean:
Obs CONPROBA CONPROBB n
1 0.09303 0.013450 0.093030.013450
2 0.09269 0.013473 0.092690.013473
3 0.28243 0.018018 0.282430.018018
4 0.14858 0.016055 0.148580.016055
5 0.10607 0.013096 0.106070.013096
So if ConprobA and ConprobB is the column 13 and 14, the column 15 would be n.
What I mean by take only column 15 is I want to treat column n as a vector. And I want to inverse it.
Then multiply with 2x1 vector I mean the column 15 multiply with a 2x1 vector.
But my way doesn't work yesterday.
I will read the link that you provide.
In the DATA step, double vertical bars (||) is the operator for string concatenation. So the following DATA step creates a CHARACTER variable z, which is the string-wise concatenation of x and y:
data a;
x=1.23; y=4.56; z = x || y;
put z;
run;
In contrast, the horizontal concatenation operator (||) in SAS/IML concatenates two vectors into a matrix that has two columns. So i n PROC IML the same statement results in a 1x2 vector:
proc iml;
x=1.23; y=4.56; z = x || y;
print z;
run;
Thank you Rick, that addressed my question.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.