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]:
| 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 |
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