Beginners Guide to Transition from SAS to Python | by ankur garg | Towards Data Science

SAS is a specialized data analytics programming language that has been around since 1976. That was 14 years before Python first appeared as a general purpose programming language in 1990 and 32 years before Pandas was first released in 2008 and transformed Python into an open source data analytics power house. While SAS is still widely respected and used across corporations because of its efficiency and support availability, Python is increasingly becoming the language of choice owing to its open source nature and rapid development of machine learning and artificial intelligence libraries. I have extensively worked with both the languages and often times get asked if there is easy guidance for people who know SAS to be able to easily transition to Python. My objective in writing this article is to develop such a guide.
We will look at 10 of the most common data analytics tasks and how you do them in SAS and in Python. The procedures and functions that I will be using have a lot more capability then what I will be presenting. However, my objective here is not to go deep into a particular procedure or function but to give a flavor of how the same tasks could be done in both languages.
I will be using the famous Titanic training dataset from Kaggle. You can download and find details about this data here. You will need both SAS and Python to follow along. Python is open source and therefore freely available to install. SAS is proprietary software but provides a free University Edition for academic and non-commercial use. This should be enough for this tutorial. Once you have access to SAS and Python, the last thing you would need is to install pandas for Python. That could be done using ‘pip’ and running the below command.
pip install pandas
Once you have successfully installed pandas, you need to import it into your Python working session. You could do that by running the code below. Notice, I like to use an alias — ‘pd’ while working with Pandas.
import pandas as pd
Let’s get started with the 10 common data analytics tasks and how you do them in SAS and Python.
Importing data is usually the most common first step in any data analytics project. Delimited flat files are often used for moving the data around. SAS provides a powerful procedure — PROC IMPORT to do this. The code below shows how to import the titanic_train.csv comma delimited file into a SAS dataset called ‘titanic’.
proc importdatafile = "&path.titanic_train.csv"out = titanicdbms = csv;run;
Pandas provides the read_csv() function to do this. Here, I am creating a Pandas DataFrame object by using read_csv() to import titanic_train file. A DataFrame is Pandas equivalent of a SAS dataset.
titanic=pd.read_csv('titanic_train.csv')
One of the first tasks after importing data is usually to look at summary statistics of numerical fields. PROC MEANS is a great utility that provides SAS users an easy way to generate this information.
PROC MEANS DATA=titanic;VAR _numeric_;OUTPUT OUT=stats;RUN;
Pandas provides an equivalent function called describe().
titanic.describe()
Below is a snapshot of the results from SAS and Python and how they compare.
Often times, we would want to look at summary statistics at the group level. For example, we may want to group the Titanic data based on gender and see how the statistics compare between males and females. In SAS, we could add CLASS or BY statements to do that.
PROC MEANS DATA=titanic;CLASS Sex;VAR _numeric_;OUTPUT OUT=stats;RUN;
In Python, Pandas provides a groupby() function that could be chained with the describe() function using dot notation to get summary at the group level.
titanic.groupby('Sex').describe()
SAS provides a powerful DATA step to manipulate rows and columns of SAS datasets. You could use the rename statement inside of a DATA step to change the name of columns.
data titanic2;set titanic;rename Pclass=passengerclass;run;
In Python, you could use the rename() function to rename column names. You could pass multiple elements inside the dictionary if you would like to update names of multiple columns.
titanic2=titanic.rename(columns={'Pclass':'passengerclass'})
It is always a good idea to keep only the columns you need to work with and drop the ones you do not need. While this may not matter a great deal in SAS, it can have performance implications when working in Python. The reason is that Pandas DataFrames reside inside memory, unlike SAS Datasets that reside on the disk. I have often used DROP and KEEP statements inside SAS DATA step to drop and keep certain columns in datasets.
data titanic2;set titanic;drop pclass;run;data titanic2;set titanic;keep pclass;run;
Pandas provides drop() function to drop columns. We could pass the list of columns we want to drop to the columns parameter of the drop() function. For keeping certain columns, we could pass the list of columns we want to keep to the slicing operator or the square braces[]. The column list is analogous to the VAR statement in PROC PRINT. Also notice, column names (and pretty much everything) is case sensitive in the case of Python. Column names are not case sensitive in SAS.
titanic2=titanic.drop(columns=['Pclass'])titanic2=titanic[['Pclass']]
Adding new columns based on existing fields is almost always required in a data analytics project. SAS DATA step makes it very easy to do. However, in some situations, it could be a little tricky to use the DATA step. For example, here I am adding a new column ‘fare_deviation’, which is calculated by subtracting the overall mean fare from the fare for every row(passenger). Thankfully, SAS provides PROC SQL to do this easily. I love PROC SQL as it provides a way to harness the power of SQL for the purpose of analytics in conjunction with other SAS procedures.
proc sql noprint;create table titanic2 asselect *,fare-mean(fare) as fare_deviation from titanic;quit;
This is easy to do in Python and in fact, could be done in just one line of code. In the code below, I am using the mean() function to calculate the mean for the column ‘Fare’ and subtracting it from the ‘Fare’ series. Every individual column making up a DataFrame could be considered a Pandas series object. A new series could be added as a DataFrame column like the way I am creating the new DataFrame column ‘Fare_deviation’.
titanic['Fare_deviation']=titanic['Fare']-titanic['Fare'].mean()
In SAS, we could use IF or WHERE statements inside a DATA step to subset rows and KEEP and DROP to subset columns.
data titanic2;set titanic;if sex='male';keep Name Sex Pclass pclass;run;
In Python, we could use the loc[] method for subsetting the data. Here, I am selecting rows for passengers who are ‘male’ and only keeping ‘Name’, ’Sex’ and ’Pclass’ columns.
titanic2=titanic.loc[titanic['Sex']=='male',['Name','Sex','Pclass']]
PROC SORT provides an ideal way to sort a dataset in SAS. The default behavior is to sort in ascending order. For sorting in the descending order, you need to add ‘descending’ following the BY statement.
proc sort data=titanic;by descending passengerid;run;
In Python, we could use sort_values() function to sort a DataFrame. The inplace parameter tells python to apply the operation and update the same DataFrame that is calling the function.
titanic.sort_values(by=['PassengerId'],ascending=False,inplace=True)
Before I could demonstrate how to perform joins, let us first create two subsets from our titanic data. I am creating a ‘titanic_a’ dataset that contains ‘passengerid’, ‘name’ and ‘sex’ columns for passengers with passengerid 887,888,889,890,891. ‘titanic_b’ dataset contains ‘passengerid’, ‘age’ and ‘survived’ columns for passengers with passengerid 887,888,889,890,891.
data titanic_a(keep=passengerid name sex) titanic_b(keep=passengerid age survived);set titanic;if (passengerid in (887,888,889,890,891)) then output titanic_a;if (passengerid in (884,885,886,887,888)) then output titanic_b;run;
Below, I am creating two Pandas DataFrames exactly like the ones I created above in SAS.
titanic_a=titanic.loc[titanic['PassengerId'].isin([887,888,889,890,891]),['PassengerId','Name','Sex']]titanic_b=titanic.loc[titanic['PassengerId'].isin([884,885,886,887,888]),['PassengerId','Age','Survived']]
Now that we have our two datasets, we are ready to look at the joins. I often like to use PROC SQL in SAS to perform joins since I find it intuitive using SQL. The MERGE statement is equally popular. In the below code, we are creating three datasets — titanic inner (resulting from the inner join on passengerid between titanic_a and titanic_b), titanic_outer (resulting from the outer join on passengerid between titanic_a and titanic_b) and titanic_left_a (resulting from the left join on passengerid between titanic_a and titanic_b).
data titanic_inner titanic_left_a titanic_outer;merge titanic_a (in = a)titanic_b (in = b);by descending passengerid;if a and b then output titanic_inner;if a then output titanic_left_a;if a or b then output titanic_outer;run;
Similar results could be achieved by using the merge() function provided by pandas.
titanic_inner=titanic_a.merge(titanic_b,how='inner',on='PassengerId')titanic_left_a=titanic_a.merge(titanic_b,how='left',on='PassengerId')titanic_outer=titanic_a.merge(titanic_b,how='outer',on='PassengerId')
The final example is to export the data as a flat file. In SAS, this could be done using PROC EXPORT.
PROC EXPORTDATA=titanic_outerDBMS=csvOUTFILE="&path.titanic_outer.csv";run;
In Python, you could write out a flat file using the to_csv() function.
titanic_outer.to_csv('titanic_outer.csv')
I hope this guide provides a good starting point to SAS programmers to try their hands at doing data analytics using Python and for Python programmers to use SAS.