Lesson 14, Part 1: SASPy¶

SASPy is a Python Application Programming Interface (API) to the SAS system

  • Enabling communication between Jupyter and SAS when using the SAS Kernel
  • Running Python code using commonly used IDE other than Jupyter Notebook
  • Loading SAS data sets into Python-Pandas DataFrame objects
  • Converting Python-Pandas DataFrame objects into SAS data sets
  • Using Python convenience methods on SAS data sets
  • Imitating the SAS macro facility
  • Generating SAS code from Python code
If you have a licensed SAS software installed in your computer and you want to use SASPy¶
  • Install the SASPy module for adding it to your Python environment
  • Configure it to connect to your SAS environment
    • Set up the sascfg_personal.py configuration file
    • Make SAS-supplied Java.jar files available to SASPy
  • Install Anaconda distribution of Python for JupyterLab
  • Install SAS kernel to enable SASPy communication between Jupyter and SAS

SASPy can be used from:

  • Jupyter Notebook or JupyterLab
  • any Python console/scripting environment
Loading a SAS data set into a Python Object using the sasdata method¶
  • Import saspy
  • Create a connection with SAS, authenticating and spinning up a SAS session; winlocal is configuration name in the setup
  • Create python object using the sasdata method
  • Run descriptive statistics
In [1]:
import saspy
sas = saspy.SASsession(cfgname='winlocal')
iris = sas.sasdata("iris","SASHELP")
iris.describe()
SAS Connection established. Subprocess id is 23244

Out[1]:
Variable Label N NMiss Median Mean StdDev Min P25 P50 P75 Max
0 SepalLength Sepal Length (mm) 150.0 0.0 58.0 58.433333 8.280661 43.0 51.0 58.0 64.0 79.0
1 SepalWidth Sepal Width (mm) 150.0 0.0 30.0 30.573333 4.358663 20.0 28.0 30.0 33.0 44.0
2 PetalLength Petal Length (mm) 150.0 0.0 43.5 37.580000 17.652982 10.0 16.0 43.5 51.0 69.0
3 PetalWidth Petal Width (mm) 150.0 0.0 13.0 11.993333 7.622377 1.0 3.0 13.0 18.0 25.0
Print() function¶
  • prints the class type of the object that is specified as the argument in the type() function.
In [3]:
print(type(iris))
<class 'saspy.sasdata.SASdata'>
Type() function¶
In [18]:
type(iris)
Out[18]:
saspy.sasdata.SASdata
Transferring a data set between SAS and Python - Paired methods¶
  • df2sd

  • sd2df

  • Retention of the data types, column names, and other basic elements on the destination side

  • Non-retention of some metadata unique to SAS data on the Python side

A Basic Introduction to SASPy and Jupyter Notebooks By Jason Philips. 2018

In [4]:
import saspy
sas = saspy.SASsession(cfgname='winlocal')
class_sds = sas.sd2df(table='class', libref='sashelp')
class_sds.describe()  
SAS Connection established. Subprocess id is 9496

Out[4]:
Age Height Weight
count 19.000000 19.000000 19.000000
mean 13.315789 62.336842 100.026316
std 1.492672 5.127075 22.773933
min 11.000000 51.300000 50.500000
25% 12.000000 58.250000 84.250000
50% 13.000000 62.800000 99.500000
75% 14.500000 65.900000 112.250000
max 16.000000 72.000000 150.000000
In [ ]:
print(type(class_sds))
Using the to_df() function for loading the SAS data set in to the pandas dataframe¶
In [6]:
import saspy
import pandas as pd
pd_iris =iris.to_df()
print(type(pd_iris))
<class 'pandas.core.frame.DataFrame'>
Using %cd magic command for referencing a SAS data set¶
In [ ]:
import saspy
import pandas as pd
sas = saspy.SASsession(cfgname='winlocal')
%cd C:\Data
p_cars = pd.read_sas('cars.sas7bdat', format='sas7bdat', encoding="utf-8")
p_cars.describe()
Documenting the codes in the next cell¶
  • Import SASPy
  • Import pandas
  • Establish SAS connection
  • Reference a SAS data set
  • Convert a SAS data set to a dataframe
  • Use the astype() function to change the data type?
  • Concatenate two strings (VARSTR and VARPSU)
In [4]:
import saspy
import pandas as pd
sas =saspy.SASsession(cfgname='winlocal')
sas.saslib(libref='new', path="C:\\CourseData")
py_obvisits17 = sas.sd2df(table='h197g', libref='new', dsopts={"keep": "dupersid var: VSTCTGRY"})
py_obvisits17 = py_obvisits17.astype({"VARSTR":'object', "VARPSU":'object'})
py_obvisits17['CLUSTER']= py_obvisits17['VARSTR'].astype(str)+py_obvisits17['VARPSU'].astype(str)
py_obvisits17.info()
SAS Connection established. Subprocess id is 9808


5                                                          The SAS System                               12:33 Friday, April 26, 2024

24         
25         libname new    'C:\CourseData'  ;
NOTE: Libref NEW was successfully assigned as follows: 
      Engine:        V9 
      Physical Name: C:\CourseData
26         
27         
28         

6                                                          The SAS System                               12:33 Friday, April 26, 2024

29         
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 170491 entries, 0 to 170490
Data columns (total 5 columns):
 #   Column    Non-Null Count   Dtype  
---  ------    --------------   -----  
 0   DUPERSID  170491 non-null  object 
 1   VSTCTGRY  170491 non-null  float64
 2   VARSTR    170491 non-null  object 
 3   VARPSU    170491 non-null  object 
 4   CLUSTER   170491 non-null  object 
dtypes: float64(1), object(4)
memory usage: 6.5+ MB
Display()¶
  • displays multiple outputs
In [22]:
import saspy
import pandas as pd
from IPython.display import display
display(len(py_obvisits17['CLUSTER'].unique().tolist()))
display(len(py_obvisits17['VARSTR'].unique().tolist()))
display(len(py_obvisits17['VARPSU'].unique().tolist()))
display(len(py_obvisits17['DUPERSID'].unique().tolist()))
621
282
3
22352
In [6]:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
len(py_obvisits17['CLUSTER'].unique().tolist())
len(py_obvisits17['VARSTR'].unique().tolist())
len(py_obvisits17['VARPSU'].unique().tolist())
len(py_obvisits17['DUPERSID'].unique().tolist())
Out[6]:
22352
Generating a profile of the Python data object created from the SAS data set¶
In [ ]:
import saspy
import pandas
import pandas_profiling
sas = saspy.SASsession(cfgname='winlocal')
df_heart = sas.sd2df(table='heart', libref='sashelp')
pandas_profiling.ProfileReport(df_heart)
Generating SAS code by using the SASPy module¶
In [9]:
import saspy
import pandas as pd
sas = saspy.SASsession(cfgname='winlocal')
w_class = sas.sasdata("CARS","SASHELP")
code=sas.teach_me_SAS(1)
w_class.columnInfo()
SAS Connection established. Subprocess id is 13800

proc contents data=SASHELP.'CARS'n ;ods select Variables;run;
Running a SAS program by using a Jupyter Notebook magic command (%%SAS)¶
In [5]:
%%SAS
proc print data=sashelp.class (obs=5); 
run;
Using SAS Config named: winlocal
SAS Connection established. Subprocess id is 57780

Out[5]:
SAS Output

The SAS System

Obs Name Sex Age Height Weight
1 Alfred M 14 69.0 112.5
2 Alice F 13 56.5 84.0
3 Barbara F 13 65.3 98.0
4 Carol F 14 62.8 102.5
5 Henry M 14 63.5 102.5

sas.submit() in saspy¶

sas.submit() is the core method in saspy that sends raw SAS code from Python to a SAS session, executes it, and returns the results.

Printing the text results¶

Instead of printing raw HTML, you can print the text results

In [20]:
import saspy
# Create the session with text results:
sas = saspy.SASsession(results='text')
results = sas.submit("""
options nocenter nodate nonumber;
    proc print data=sashelp.class(obs=5);
    run;
""")
print(results['LST'])  # View the SAS output
Using SAS Config named: winlocal
SAS Connection established. Subprocess id is 9784


The SAS System

Obs     Name      Sex    Age    Height    Weight

  1    Alfred      M      14     69.0      112.5
  2    Alice       F      13     56.5       84.0
  3    Barbara     F      13     65.3       98.0
  4    Carol       F      14     62.8      102.5
  5    Henry       M      14     63.5      102.5

Pulling the SAS dataset into a DataFrame in Python¶

Since you’re already in Python, pulling the SAS dataset into a DataFrame is often easier. This avoids ODS HTML entirely and gives you a normal pandas DataFrame for analysis.

In [17]:
import saspy
import pandas as pd

sas = saspy.SASsession()

df = sas.sasdata2dataframe(
    table='class',
    libref='sashelp'
)

print(df.head(3))
Using SAS Config named: winlocal
SAS Connection established. Subprocess id is 11624

      Name Sex   Age  Height  Weight
0   Alfred   M  14.0    69.0   112.5
1    Alice   F  13.0    56.5    84.0
2  Barbara   F  13.0    65.3    98.0

Tips, Tricks, Hacks, and Magic: How to Effortlessly Optimize Your Jupyter Notebook by Anne Bonner

Profiling and Optimizing Jupyter Notebooks - A Comprehensive Guide by Muriz Serifovic