While growing up in the 80's, I watched The Golden Girls on TV with my Grandma Betty. Now, when my sister visits, we binge watch reruns on TV Land. I was excited when I saw for this Halloween, you could buy Golden Girls costumes! Too bad they sold out right away, making them one this year's most popular costumes.
For the record, I wasn't planning to dress up tonight as a Golden Girl, but the news got me to thinking how Halloween costumes have changed over the years. What was popular when? Hence, this post. I explain how to use SAS REST APIs to append a table containing historic costume data with this year's most popular costumes (including the Golden Girls and Pennywise from It). While looking at costume data in this example, consider the append steps as a template to translate any table needing updates in SAS Viya, using REST APIs.
The data
I created a data set containing the most popular Halloween costumes from the last 50 years (1968-2018). I compiled the data from several sources who couldn't seem to agree on the best-selling costume for a given year, so I combined the lists. Many years have two entries. The data here isn't as important as the append table procedure. What fun to review the costumes list! It was not hard to tell in what year certain movies (and their sequels) were released. Only one costume I wore made the list – my 1979 Ace Frehley outfit!
The process
The procedures in this example run on SAS Viya, utilizing the Cloud Analytics Services (CAS) REST APIs. CAS REST APIs use CAS actions to perform statistical methods across a variety of SAS products. You can learn more about CAS REST APIs and CAS Actions in the Using SAS Cloud Analytics Service REST APIs to run CAS Actions post or on developer.sas.com.
Below, I'll detail each REST call along with sample code. I originally used Postman to organize my calls. This allowed me to utilize pre and post-call scripting to handle responses and create variables. You can find the entire Postman collection here on GitHub. For ease-of-display purposes in this post, I'll use equivalent cURL commands.
Pre-requisites
I registered my client, obtained access token, and added it as an environment variable ACCESSTOKEN. For more information on registering a client or getting an access token, see my earlier post Authentication to SAS Viya: a couple of approaches.
Create a CAS session
Before running any CAS actions, we need to establish a connection to the SAS Viya server.
curl -X POST https://sasserver:8777/cas/sessions \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/vnd.sas.cas.session+json' |
The result of this call is a session id in the form of a089ce2b-8116-7a40-b3e3-6e39b7b5566d
. This will be used in all subsequent REST calls. You could easily create another variable for further use. In the examples below I substitute the actual session id with <session-id>. You will need to substitute this place holder when attempting the steps on your own.
Create a global Caslib HALLOWEEN
Data in CAS is stored in a Caslib. In the step below, I create a Caslib called HALLOWEEN and link it to a physical server path (/home/sasdemo/halloween), where the table is stored.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/actions/table.addCaslib \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"name":"HALLOWEEN","path":"/home/sasdemo/halloween","description":"HALLOWEEN","subDirectories":"false","permission":"PUBLICWRITE","session":"false","dataSource":{"srcType":"path"},"createDirectory":"true","hidden":"false","transient":"false"} |
Note that I created the directory ~/halloween and set permissions as needed. Further, since the Caslib is global, other users have access to the data. This step (and the next step) are one time requests. If you were to repeat this process you would not need to create the Caslib nor upload the data.
Copy data set costumesByYear into HALLOWEEN's path
Now that we have a Caslib and a path, we load the data table to the server. In this instance, I copy the costumesByYear.xlsx file into /home/sasdemo/halloween. There are multiple ways to upload data to the server. You can read more about the various methods in the SAS documentation.
Create a temporary Caslib TEMP
While our data lives in the HALLOWEEN Caslib, we want to create a temporary Caslib to run the append step. We will then save the appended table back into HALLOWEEN. The following code creates a new Caslib called TEMP.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/actions/table.addCaslib \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"name":"TEMP","path":"/home/sasdemo/temp","description":"TEMP","subDirectories":"false","permission":"PUBLICWRITE","session":"false","dataSource":{"srcType":"path"},"createDirectory":"true","hidden":"false","transient":"false"} |
Now we're ready to load the data into memory and append the table.
Load costumesByYear into memory
First, we load costumesByYear into memory in the TEMP Caslib.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/actions/table.loadTable -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"path":"costumesByYear.xlsx","caslib":"HALLOWEEN","importOptions":{"fileType":"EXCEL"},"casOut":{"caslib":"TEMP","name":"costumesByYear","promote":"true"}} |
Create a temporary table data2019 with containing append data
Next, we create a new table called data2019 with costume data for 2019 in TEMP.
curl -X PUT https://sasserver:8777/cas/sessions/<session-id>/actions/upload -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: text/plain' \ -H 'JSON-Parameters: {"casOut":{"caslib":"TEMP","name":"data2019","promote":"true"},"importOptions":{"fileType":"CSV"}}' \ --data-binary $'Year,Costume\n2019,The Golden Girls\n2019,Pennywise' |
Run data step to append data2019 to costumesByYear table
Finally, we run data step code to append table data2019 to table costumesByYear.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/actions/runCode \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"code": "data temp.costumesbyyear(append=force) ; set temp.data2019;run;"} |
Save the costumesByYear table back to the HALLOWEEN CASlib
Now that we have successfully appended the costumesByYear table in the TEMP Caslib, we are ready to save back to the HALLOWEEN Caslib.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/actions/table.save \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"table":{"name":"costumesbyyear","caslib":"TEMP","singlePass":"false"},"name":"costumesbyyear","replace":"true","compress":"false","caslib":"HALLOWEEN","exportOptions":{"fileType":"BASESAS"}} |
Delete TEMP Caslib
The TEMP Caslib is just that, temporary. With the code below we drop the Caslib and all its data.
curl -X POST https://sasserver:8777/cas/sessions/<session-id>/table.dropCaslib \ -H 'Authorization: Bearer $ACCESSTOKEN' \ -H 'Content-Type: application/json' \ -d {"caslib":"TEMP"} |
Delete the CAS session
The final step is to close our connection to the CAS server.
curl -X DELETE https://sasserver:8777/cas/sessions/<session-id> \ -H 'Authorization: Bearer $ACCESSTOKEN' |
Wrapping it up
There you have it. With a few simple commands we were able to load, append, and save a table. This example is fairly simple in scope, but translates into more complex use cases. The steps for my 2 x 50 table are the same as it would be for a 5GB table with hundreds of columns and millions of rows.
I have asked my mother to send the Polaroid photo of me as Ace in 1979. She just has to dig it out of a photo album. Check back in a week so you can gain fodder and poke fun at me.
Additional Resources
developer.sas.com - developers site for SAS
GitHub resources - GitHub repository for code used in this post
SAS Viya CAS REST API: How to fetch a table? - Related article from SAS Communities