Dynamically split/create multiple datasets from single dataset in SAS | by Pramod K | Towards Data Science

Splitting a dataset into multiple datasets is a challenge often faced by SAS programmers. For example, splitting data collected from all over the world into unique country-wise datasets, where each datsaset contains data specific only to that country. In such scenarios, programmers are often forced to hard code the program and use multiple loops to get the job done, which is not a good practice. SAS, however, provides a beautiful, one-time, reusable solution to this problem. Let’s get straight into it.
We have the following worldwide sales dataset with us (Worldwide_Sales.xls):
All datasets and code files can be found at GitHub ( https://github.com/pramodkumavat/createMultipleDatasets/ ).
Let’s first import this dataset into our SAS environment.
P.S : Please copy the dataset file Worldwide_Sales.xls into your SAS working directory myfolders.
proc import out=work.salesdatafile='/folders/myfolders/Worldwide_Sales.xls'dbms=xls replace;getnames=yes;run;
Running the above code will load our dataset as work.sales library in SAS.
To understand the various options used in the import code, this FAQ is all you need.
The business requirement says that we must create country-wise unique datasets from the worldwide dataset. Each dataset thus created will have sales data for that specific country. To achieve this, we will first need to extract the unique country names from the dataset.
proc sort data=work.sales out=work.unique (keep=Country)nodupkey;by country;run;
Running the above code will give us the unique country names from the dataset.
Once we have extracted the country names, let’s now create our magic code to dynamically create country-wise datasets inside single data statement.
data _null_;set work.unique;call execute('data ' !! compress(Country) !! '; set work.sales; where Country = "' !! Country !! '"; run;');run;
As you can see in the above output, on the left-hand side, we see country-wise unique datasets have been created.
Let’s understand each aspect of the code line by line that makes this magic possible.
data _null_;
We set the output data as _null_ because we don’t want to create a single dataset, but multiple datasets at once, which we we’ll see in some time.
set work.unique;
We set the input dataset as work.unique, which contains unique country names. We do this because we will want unique country-wise datasets to be created on each iteration.
call execute('data ' !! compress(Country) !! '; set work.sales; where Country = "' !! Country !! '"; run;');run;
This is the real deal! You might have noticed that we have written a nested query inside the call execute() statement. As mentioned earlier, SAS provides this beautiful solution to create multiple datasets without using multiple loops.
Inside the execute() call, we start with the data statement and then append it with our unique country name. Country here is nothing but the variable from our work.unique dataset. The compress function is applied to the Country variable because we have country names with whitespaces in them (for example, New Zealand, United Kingdom). This compress function removes the whitespace from the country names when creating unique datasets.
Then we put semicolon(;) to end our data step and then set the input dataset as work.sales. It is obvious that we set input as our parent dataset work.sales using which we will create unique datasets. Then, we put the where condition so that it picks country-wise data from the parent dataset. Then we end the nested query with the run statement and close the execute() call. The last run statement of the code is to end the outer query.
I’m pasting the full SAS code here for your reference. This SAS code (dynamicMultipleDatasets.sas) along with the dataset used (Worldwide_Sales.xls) can be download from GitHub here.
* Importing the dataset in SAS;proc import out=work.salesdatafile='/folders/myfolders/Worldwide_Sales.xls'dbms=xls replace;getnames=yes;run;* Extracting country names from the dataset;proc sort data=work.sales out=work.unique (keep=Country)nodupkey;by country;run;* Creating multiple datasets from the parent dataset;data _null_;set work.unique;call execute('data ' !! compress(Country) !! '; set work.sales; where Country = "' !! Country !! '"; run;');run;
Hope this was helpful. Please comment your feedback/suggestions. Cheers!