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

I am trying to extract multiple items from a SAS/IML list. I have limited success using colvec() and rowvec() but when I try to simplify my code, I run into syntax errors that I do not understand. Here is my code:

proc iml ;
package load listutil ;

e = [ #'nobs' =3
      , #'nvars'=2
      , #'type' =[ 'N' ] || [ 'N' ]
      , #'name' =[ 'var1' ] || [ 'var2' ]
      , #'cols' =[{ 11 21 31 }] || [{ 12 22 32 }]
      ] ;

call listprint( e ) ;

 

columns = colvec( e$'cols'$1 ) || colvec( e$'cols'$2 ) ; /* this is awkward but "columns = e$'cols'$1 || e$'cols'$2" gives me a list and I want a numeric matrix */


print columns ;

colnames = rowvec( e$'name'$1 ) || rowvec( e$'name'$2 ) ; /* same reason as for columns, above */
print colnames ;

 

tbl = TableCreate( colnames, columns ) ; /* this code works, but getting to this point is inelegant, IMHO */
call TablePrint( tbl ) ;

sublist = [ 1:2 ] ;
a = e$'cols'$sublist ; /* is this the correct syntax? the SAS/IML interpreter thinks otherwise */
call listprint ( a ) ;
quit ;

 

I want to extract columns 1 and 2 from list item e$'cols' with one subsetting operation so I defined a sublist and tried to define list a, but failed. Where am I going wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

Your confusion is caused because the brackets ([...]) are used both for subscript operations and to define lists. If you want to extract the 1st and 2nd items in a list, use the subscript operator:

idx = 1:2;
a = e$'cols'[idx]; /* subscripts, not a list */
call listprint ( a ) ;

With regard to your meta-question ("extracting the data is inelegant"), I suggest that you might benefit by rethinking your data structure. Here are a few concrete suggestions:

  • Don't make everything in 'e' a list. If a component contains homogeneous elements (such as 'type' and 'name'), make it a vector or matrix. 
  • Store the elements of 'cols' as column vectors to eliminate having to call COLVEC every time you retrieve a column
  • Use the TableAddVar function to construct a table. Your current method will fail if you have both numerical and character data.
  • I prefer CALL STRUCT to CALL LISTPRINT. It provides a nice summary of the structure of the list and its items and subitems.

The following program might give you some ideas to play with:

 

proc iml ;
package load listutil ;

/* if data are homogeneous, use a matrix instead of a list */
e = [ #'nobs' =3
      , #'nvars'=3
      , #'type' ={'N' 'N' 'N'}
      , #'name' ={'var1' 'var2' 'var3'}
      , #'cols' =[{ 11, 21, 31 }, { 12, 22, 32 }, {A, B, C}]
      ] ;

call struct( e ) ;

/* to create a table from names and columns, use TableAddVar */
varIdx = {1 3};
tbl = TableCreate();
do i = 1 to ncol(varIdx);
   k = varIdx[i];
   call TableAddVar(tbl, e$'name'[k], e$'cols'$k);
end;
call TablePrint( tbl ) ;

View solution in original post

3 REPLIES 3
Ksharp
Super User
Post it at IML forum and calling @Rick_SAS
rbettinger
Pyrite | Level 9

Thank you for calling my attention to the 'SAS/IML' forum and Rick Wicklin.

Rick_SAS
SAS Super FREQ

Your confusion is caused because the brackets ([...]) are used both for subscript operations and to define lists. If you want to extract the 1st and 2nd items in a list, use the subscript operator:

idx = 1:2;
a = e$'cols'[idx]; /* subscripts, not a list */
call listprint ( a ) ;

With regard to your meta-question ("extracting the data is inelegant"), I suggest that you might benefit by rethinking your data structure. Here are a few concrete suggestions:

  • Don't make everything in 'e' a list. If a component contains homogeneous elements (such as 'type' and 'name'), make it a vector or matrix. 
  • Store the elements of 'cols' as column vectors to eliminate having to call COLVEC every time you retrieve a column
  • Use the TableAddVar function to construct a table. Your current method will fail if you have both numerical and character data.
  • I prefer CALL STRUCT to CALL LISTPRINT. It provides a nice summary of the structure of the list and its items and subitems.

The following program might give you some ideas to play with:

 

proc iml ;
package load listutil ;

/* if data are homogeneous, use a matrix instead of a list */
e = [ #'nobs' =3
      , #'nvars'=3
      , #'type' ={'N' 'N' 'N'}
      , #'name' ={'var1' 'var2' 'var3'}
      , #'cols' =[{ 11, 21, 31 }, { 12, 22, 32 }, {A, B, C}]
      ] ;

call struct( e ) ;

/* to create a table from names and columns, use TableAddVar */
varIdx = {1 3};
tbl = TableCreate();
do i = 1 to ncol(varIdx);
   k = varIdx[i];
   call TableAddVar(tbl, e$'name'[k], e$'cols'$k);
end;
call TablePrint( tbl ) ;

sas-innovate-wordmark-2025-midnight.png

Register Today!

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.


Register now!

Multiple Linear Regression in SAS

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.

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 3 replies
  • 1185 views
  • 1 like
  • 3 in conversation