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

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

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