BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
mgrasmussen
Quartz | Level 8

Dear SAS experts

 

I have some code which I cannot get to work. I want to use the data points for each numeric variable in the first observation and divide by this number in the data points below the first observation. I can get it to work if I take one variable at a time, but I cannot get the code with an array to work. Specifically, I cannot seem to define the variable which is retained and used in the simple calculation (see ?????). Does anyone have a suggestion on how get the code to work using an array? Thank you.

 


data have;
input varone vartwo varthree varfour;
datalines;
1 2 1.5 5
1 2 1 1
1 3 1 2
1 4 3 10
;
run;

 

data have;
set have;
globalcatvar="1";
run;

 

*No array;
data want_three;
set have;
by globalcatvar;
retain firstvartwo;
if first.globalcatvar then firstvartwo=vartwo;
if _n_>1 then vartwo=vartwo/firstvartwo;
run;

 

*With array;
data want_three;
set have;
array modify {*} _NUMERIC_;
do i=1 to dim(modify);
by globalcatvar;
retain ?????;
if first.globalcatvar then ?????=modify{i};
if _n_>1 then modify{i}=modify{i}/?????;
end;
run;

1 ACCEPTED SOLUTION

Accepted Solutions
s_lassen
Meteorite | Level 14

I think the right approach is to use a _TEMPORARY_ array, these are automatically retained:

data want_three;
set have;
by globalcatvar;
array modify {*} _NUMERIC_;
array retains (200) 8 _temporary_;
if first.globalcatvar  then do i=1 to dim(modify);
  retains(i)=modify(i);
  end;
else do i=1 to dim(modify);
  modify{i}=modify{i}/retains(i);
  end;
run;

 

View solution in original post

9 REPLIES 9
andreas_lds
Jade | Level 19

Please show the expected result.

You may need to arrays, one for the values in the current observation, another one for the retained variables, both need variable-names, _numeric_ won't work.

mgrasmussen
Quartz | Level 8

Hey Andreas

 

Thanks.

 

For vartwo, I would like it to make the following change:

 

2 = 2 (no change)

2 = 2/2 = 1

3 = 3/2 = 1.5

4 = 4/2 = 2

 

Specifically, each number is divided by the first data point.

 

So some code which looks something like this (although the array does not work)?

 

data have;
input varone vartwo varthree varfour;
datalines;
1 2 1.5 5
1 2 1 1
1 3 1 2
1 4 3 10
;
run;

 

data have;
set have;
globalcatvar="1";
run;

 

*Array:
data want_three;
set have;
array modify {4} varone vartwo varthree varfour;
array modify_r {4} varone_r vartwo_r varthree_r varfour_r;
do i=1 to 4;
by globalcatvar;
retain modify_r{i};
if first.globalcatvar then modify_r{i}=modify{i};
if _n_>1 then modify{i}=modify{i}/modify_r{i};
end;
run;

andreas_lds
Jade | Level 19

Still not clear, why globalcatvar is defined ... the following step is build on some assumptions:

- you want to divide varthree and varfour also

- varone is constant

 

data want;
   set have;
   
   array vars[3] vartwo varthree varfour;
   array re[3] _temporary_;
   
   if _n_ = 1 then do;
      do i = 1 to dim(re);
         re[i] = vars[i];
      end;
   end;
   else do;
      do i = 1 to dim(re);
         vars[i] = vars[i] / re[i];
      end;      
   end;
   
   drop i;
run;
   
mgrasmussen
Quartz | Level 8

Hey Andreas

 

Thanks. No, I might not need globalcatvar.

 

Your code looks interesting. Is it possible to modify it such that all numeric variables are included in vars (and that the rest of the code can be modified to work too)?

 

Thanks

andreas_lds
Jade | Level 19

untested:

proc sql noprint;
  select num_numeric into :numVars trimmed
    from sashelp.vtable
      where libname = 'WORK' and memname = 'HAVE'
  ;
quit;

data want;
   set have;
   
   array vars _numeric_; 
   array re[&numVars.] _temporary_;
   
   if _n_ = 1 then do;
      do i = 1 to dim(re);
         re[i] = vars[i];
      end;
   end;
   else do;
      do i = 1 to dim(re);
         vars[i] = vars[i] / re[i];
      end;      
   end;
   
   drop i;
run;
   


s_lassen
Meteorite | Level 14

I think the right approach is to use a _TEMPORARY_ array, these are automatically retained:

data want_three;
set have;
by globalcatvar;
array modify {*} _NUMERIC_;
array retains (200) 8 _temporary_;
if first.globalcatvar  then do i=1 to dim(modify);
  retains(i)=modify(i);
  end;
else do i=1 to dim(modify);
  modify{i}=modify{i}/retains(i);
  end;
run;

 

mgrasmussen
Quartz | Level 8

Hey s_lassen

 

The code looks very cool. Thanks.

 

But what is the signifiance of (200) and 8 specified in the array 'retains'? Is 200 just a large number (could e.g. also have been 400) ?

 

Thanks 

s_lassen
Meteorite | Level 14

200 is just a number that I assume is larger than the dimension of of the other array, but not so large that it takes up all available memory. There is probably no problem in increasing it to e.g. 2000 if you sometimes have that many numeric variables.

 

8 is just the length of the array elements, as there is no dollar sign, it defines the _TEMPORARY_ array as numeric.

mgrasmussen
Quartz | Level 8

By "dimension" do you mean number of elements in the array?

So the "8" says something about how large the numbers included in the array retains are expected to be?

I am relatively new to SAS coding.

 

I slightly changed some of your code. I removed the the by-code and the globalcatvar, which I thought was neccessary. The code seems to be doing what I was hoping for. Moreover, it does appear that the code below would work without any knowledge about the number of numeric variables in the dataset?

 

data have;
input varone vartwo varthree varfour;
datalines;
1.1 2 1.5 5
1 2 1 1
1 3 1 2
1 4 3 10
;
run;

 

data want_three;
set have;
array modify {*} _NUMERIC_;
array retains (200) 8 _temporary_;
if _n_=1 then do i=1 to dim(modify);
retains(i)=modify(i);
end;
else do i=1 to dim(modify);
modify{i}=modify{i}/retains(i);
end;
run;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 9 replies
  • 693 views
  • 5 likes
  • 3 in conversation