Error when assign value for matrix in iml procedure - sas

I simply want to assign a row of matrix by a vector in iml procedure, but it returns error. The code is as follow, how can I fixed it?
proc iml;
za=repeat(0,4,3);
a=123;
b=321;
c=222;
za[1,]={a,b,c};
run;
print(za);
proc print;run;

There are a few problems with your code. {x, y, z} is a column vector. {x y z} is a row vector. Which means you attempt to insert a column in a row. Also, the syntax is a bit off.
Using your own code, you can do this.
proc iml;
za=repeat(0,4,3);
a=123;
b=321;
c=222;
za[1,] = a || b || c;
print(za);
quit;
A simpler way would be
proc iml;
za = j(4, 3, 0);
v = {123 321 222};
za[1, ] = v;
print za;
quit;

Related

Replacing values of a column with its minimum value in sas

i am very new to sas and I have the following work table
I want to create a new table in which column Date and Z remain the same, but all values in column X are replaced with the minimum value in column X and all values in column Y are replaced with the minimum value in column y.
Sample output is as follows
You can use the fact that PROC SQL will automatically remerge aggregate statistics back onto detail observations.
proc sql;
create table want as
select date, x, min(y) as y, min(z) as z
from have
;
quit;
If you don't want to use proc sql statement you can modify this code found from https://blogs.sas.com/content/iml/2014/12/01/max-and-min-rows-and-cols.html
data MinMaxRows;
set sashelp.Iris;
array x {*} _numeric_; /* x[1] is 1st var,...,x[4] is 4th var */
min = min(of x[*]); /* min value for this observation */
max = max(of x[*]); /* max value for this observation */
run;
proc print data=MinMaxRows(obs=7);
var _numeric_;
run;

SAS - proc sql - select columns belonging together?

I want to split a table with many (454) columns in a PROC SQL (perhaps using a macro?) by column names.
For example: a column is starting with "Column21....T", "Column22....T", etc.
I want to write all those columns starting with "Column21...T" to a data set called First, and all the columns starting with "Column22....T" to a data set called Second, etc.
I want to retain the first and second column of the transposed table because they contain the descriptional rows.
I cannot use select column1, column2.... Column454 because of the large number of columns.
How do I do this?
(#Mod: thanks for the clean-up :))
Edit, one picture to say it all:
This is my transposed table with 454 columns
PROC SORT
DATA=work.stat(KEEP=A_ B_ C_ D_ Vx G Vy)
OUT=work.stat2;
BY G;
RUN;
PROC TRANSPOSE DATA=work.stat2
OUT=WORK.x(LABEL="Transposed")
PREFIX=Column
LET
NAME=Source
LABEL=Label;
BY G;
ID Vx;
IDLABEL Vy;
VAR A_ B_ C_ D_;
RUN;
You can use : suffix to make a variable list.
data first ;
set have ;
keep id1 id2 column21: ;
run;
data second ;
set have ;
keep id1 id2 column22: ;
run;
Updated given more details in question.
So why not just transpose each group separately? Make a macro to transpose one value of Vx.
%macro split(value);
PROC TRANSPOSE DATA=work.stat2
OUT=WORK.Column&value (LABEL="Transposed Vx=&value")
PREFIX=Column
LET
NAME=Source
LABEL=Label
;
BY G;
WHERE Vx=&value ;
ID Vx;
IDLABEL Vy;
VAR A_ B_ C_ D_;
RUN;
%mend split ;
Then call it once for each value of Vx.
proc sort data=work.stat2(keep=Vx) nodupkey out=Vx_list ;
by Vx ;
run;
data _null_;
set Vx_list;
call execute(cats('%nrstr(%split)(',Vx,')'));
run;
Macro program:
%macro split(data,outdata);
%do i=21 %to 121;
data &outdata.&i;
set &data;
keep id1 id2 col&i:;
run;
%end;
%mend;

Do loop and If statement in Proc IML

I have table1 that contains one column (city), I have a second table (table2) that has two columns (city, distance),
I am trying to create a third table, table 3, this table contains two columns (city, distance), the city in table 3 will come from the city column in table1 and the distance will be the corresponding distance in table2.
I tried doing this using Proc IML based on Joe's suggestion and this is what I have.
proc iml;
use Table1;
read all var _CHAR_ into Var2 ;
use Table2;
read all var _NUM_ into Var4;
read all var _CHAR_ into Var5;
do i=1 to nrow(Var2);
do j=1 to nrow(Var5);
if Var2[i,1] = Var5[j,1] then
x[i] = Var4[i];
end;
create Table3 from x;
append from x;
close Table3 ;
quit;
I am getting an error, matrix x has not been set to a value. Can somebody please help me here. Thanks in advance.
The technique you want to use is called the "unique-loc technique". It enables you to loop over unique values of a categorical variable (in this case, unique cities) and do something for each value (in this case, copy the distance into another array).
So that others can reprodce the idea, I've imbedded the data directly into the program:
T1_City = {"Gould","Boise City","Felt","Gould","Gould"};
T2_City = {"Gould","Boise City","Felt"};
T2_Dist = {10, 15, 12};
T1_Dist = j(nrow(T1_City),1,.); /* allocate vector for results */
do i = 1 to nrow(T2_City);
idx = loc(T1_City = T2_City[i]);
if ncol(idx)>0 then
T1_Dist[idx] = T2_Dist[i];
end;
print T1_City T1_Dist;
The IF-THEN statement is to prevent in case there are cities in Table2 that are not in Table1. You can read about why it is important to use that IF-THEN statement. The IF-THEN statement is not needed if Table2 contains all unique elements of Table1 cities.
This technique is discussed and used extensively in my book Statistical Programming with SAS/IML Software.
You need a nested loop, or to use a function that finds a value in another matrix.
IE:
do i = 1 to nrow(table1);
do j = 1 to nrow(table2);
...
end;
end;

SAS Vector plot: disappearance of vector lines

I have been trying to make a Vector plot in SAS using the SAShelp library 'Class'. The goal is to make a vector plot with the origins of the vectors in the respective means of the x and y variables. I used the following code:
DATA class2;
SET Sashelp.class;
x = mean(height);
y=mean(weight);
run;
PROC SGPLOT DATA = class2;
VECTOR X = height Y = weight / XORIGIN = x YORIGIN = y;
run;
I thus first created two new variables, containing the means of the X and Y variable. Then I wanted to place the origin of the vectors in these origins, but when I do this, the vectors disappear in my plot and all I get is a plot with some dots.
Any suggestions on how to solve this, and especially, how this disappearance of the vectors has been caused?
Thank you in advance,
Koen
The mean() function does not work across the entire data set. Data Steps deal with a single record at a time (think of it as SAS writing an outer loop for processing for you.
You can use SQL to get the means and then add them to the data set. I also added data labels for you.
proc sql noprint;
select mean(height), mean(weight)
into :mh, :mw
from class2;
quit;
DATA class2;
SET Sashelp.class;
x = &mh;
y= &mw;
run;
PROC SGPLOT DATA = class2;
VECTOR X = height Y = weight / XORIGIN = x YORIGIN = y datalabel=name;
run;
Produces this:

SAS Proc IML: Do Loop to Populate a Matrix

I have the following code that works great in MATLAB and I which to transpose in SAS/PROC IML:
[row col] = size(coeff);
A_temp = zeros(row,col);
for i = 1: row/6
A_temp(6*(i-1)+1:6*i,:) = coeff(6*(i-1)+1:6*i,4:col);end;
In Proc IML I do the following:
proc iml;
use i.coeff;
read all var {...} into coeff;
print coeff;
row=NROW(coeff);
print row;
col=NCOL(coeff);
print col;
A_temp=J(row,col,0); *create zero matrix;
print A_temp;
Do i=1 TO row/6;
A_temp[(6*(i-1)+1):(6*i),]=coeff[(6*(i-1)+1):(6*i),(4:col)];
END;
quit;
The code breaks down at the DO loop "(execution) Matrices do not conform to the operation.
"...why? If I understand correctly in PROC IML if I wish to select all column (in MATLAB this would be ":") but in SAS IML I simply leave it blank
You should specify it correctly. A[rows,] means ALL columns of A, not just any number of them. See this simplified example:
proc iml;
/* use i.coeff;
read all var {...} into coeff;
print coeff;
*/
coeff = J(15,10,3);
row=NROW(coeff);
print row;
col=NCOL(coeff);
print col;
A_temp=J(row,col,0); *create zero matrix;
print A_temp;
Do i=1 TO row;
* does not work; *A_temp[i,]=coeff[i,(4:col)];
A_temp[i,1:col-3]=coeff[i,(4:col)];
END;
quit;