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

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
Lapis Lazuli | Level 10

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 ) ;

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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