I have generated the tables of Forecast_2013 to 2022 in a loop and then merged all datasets in to 1 Table. But now I want to do merge the datasets in a loop with irrespective of years, The next year will be 2023 or 2024...I dont want to do mannually to set Forecast_2023;set forecast_2024. How can I put in to loop using macro?
Data P_OT.FORECAST(DROP=td qq AGE1 AGE2 AGE3 AGE4 AGEBANDFCST020 AGEBANDFCST030 AGEBANDFCST035P
HSI1_2012 HSI1_2013 HSI1_2014 HSI1_2015 HSI1_2016 HSI1_2017 HSI1_2018 HSI1_2019 HSI1_2020 HSI1_2021 HSI1_2022);
set FORECAST_2013;set FORECAST_2014;set FORECAST_2015;set FORECAST_2016;
set FORECAST_2017;set FORECAST_2018;set FORECAST_2019;set FORECAST_2020;
set FORECAST_2021;set FORECAST_2022;
run;
An alternative to what Scott posted would be:
*Assign library to folder where FORECAST_ files are located;
libname NAME 'C:\Path to Folder';
*Data step to stack files;
Data P_OT.FORECAST(DROP=td qq AGE1 AGE2 AGE3 AGE4 AGEBANDFCST020
AGEBANDFCST030 AGEBANDFCST035P HSI1_:);
set NAME.FORECAST_:;
run;
This should give the same results as what Scott posted using name prefix lists instead of using SQL to produce lists of datasets to be merged and variables to be dropped.
The code above will stack all datasets in the libname library that start with "FORECAST_". It will also drop all variables in the created dataset that begin with "HSI1_".
You can use proc sql and the sashelp.vcolumn table to find the names of all your tables and create a macro variable containing them. To do this all your tables need to be in the same library, and any other tables in the library can not contain FORCAST_. The part of the sql code that says memname like '%FORECAST_%' is doing a search on all the tables in the library called libname to select the tables that contain FORCAST_. The sql step creates a list of your tables that you can then inject into your data step to stack them.
Again: Be careful there are not other tables with the name like FORECAST_ or it will try to stack tables you do not want. The easiest way to ensure this would be to put them in their own library when you create these tables.
If you have all these tables in the work library then replace libname with work
I'm on my phone and haven't checked the substr and index part, but if i recall correctly that should work.
proc sql noprint;
select "libname."||memname
into :stack_tables separated by ' '
from sashelp.vcolumn
where libname = upper("libname")
and
memname like '%FORECAST_%'
;
select "HSI1_"||substr(memname,index(memname,"_")+1,4)
into :drop_vars separated by ' '
from sashelp.vcolumn
where libname = upper("libname")
and
memname like '%FORECAST_%'
;
quit;
Data P_OT.FORECAST(DROP=td qq AGE1 AGE2 AGE3 AGE4 AGEBANDFCST020 AGEBANDFCST030 AGEBANDFCST035P
&drop_vars.);
set &stack_tables.;
run;
Related
i am working with a library that is updated every month or so, and i need a way to select the most recent dataset each month, i tried two methods that would show me the latest table, one that makes a table ordering from the modified date
proc sql;
create table tables as
select memname, modate
from dictionary.tables
where libname = 'SASHELP'
order by modate desc;
quit;
and one that gives me just the latest modified one
proc sql;
select memname into> latest_dataset
from dictionary.tables
where libname='WORK'
having crdate=max(crate);
%put &=latest_dataset;
and i would like to put these latest datasets in a table, but i don't know how, or if there is another easier way to do this, i am still very much new to SAS programming so i'm lost, any help is appreciated.
Use Proc APPEND to put the latest data set into a table. You are essentially accumulating rows.
Use SQL :INTO to obtain (place into a macro variable) the libname.memname of the data set that should be appended.
Example:
The task of determining the newest data set and appending it to a base table is also in a macro so the the code can be easily rerun in the example.
%macro append_newest;
%local newest_table;
proc sql noprint;
select catx('.', libname, memname) into :newest_table
from dictionary.tables
where libname = 'WORK'
and memtype = 'DATA'
having crdate = max(crdate);
%put NOTE: &=newest_table;
create view newest_view as
select "&newest_table" as row_source length=41, *
from &newest_table
;
proc append base=work.master data=newest_view;
run;
%mend;
* create an empty for accumulating new observations;
data work.master;
length row_source $41;
set one (obs=0);
run;
data work.one;
set sashelp.class;
where name between 'A' and 'E';
%append_newest;
data work.two;
set sashelp.class;
where name between 'Q' and 'ZZ';
%append_newest;
data work.three;
set sashelp.class;
where name between 'E' and 'Q';
%append_newest;
Will produce this master table that accumulates the little pieces that come in day by day.
You would want additional constraints such as a unique key in order to prevent appending the same data more than once.
hi am trying to append the data-sets from a library which contain a specific column variable in them.for example i want to append those data-sets which contain the name column in them from myfile library.
below is my sample code--->
libname myfile'\c:data';
proc sql noprint ;
select distinct catx(".",libname,memname) into :DataList separated by " "
from dictionary.columns
where libname = upcase(myfile) and upcase(name);
quit;
Assuming that the type of the variable is consistent across all datasets something as simple as SET will work:
Data want;
Set &datalist;
Run;
I am trying to read a list of values into a macro, so that the macro variable would contain the table name and create a column that would contain the table name.
My attempt, which is wrong, was trying to use the code below, and erroring out because of the line " '&tbl' as Table_Dt ". The code below is inefficient, so feel free to enhance it. Thanks for your help.
%macro flat(tbl);
proc sql exec feedback stimer noprint outobs=5;
CREATE TABLE &tbl as
SELECT
ID,
DOB,
'&tbl' as Table_Dt
FROM &tbl..flat_file;
QUIT;
%mend flat;
%flat(flat0113);
%flat(flat0213);
...
%flat(flat1213);
As you are basically processing a list, this could also be done using call execute. No need to write all the information to macro variables. All tables/libraries are already stored in the sashelp tables and therefore are ready for list processing.
data _null_;
set sashelp.vslib (where=(substr(libname,1,4) = 'FLAT')) end =eof;
if _n_ = 1 then call execute ('proc sql exec feedback stimer noprint outobs=5;');
call execute ('
CREATE TABLE '|| libname ||' AS
SELECT ID,
DOB,
"'||compress(libname)||'" as Table_Dt
FROM '||compress(libname)||'.flat_file
;
');
if eof then call execute ('QUIT;');
run;
Macros in quotation marks will only resolve with double quotes, not single. If you want to do a more efficient way, you can do so with the following modified code. I am assuming that you are reading from libraries named flat0113, flat0213, etc.
Step 1: Get a list of all the libnames with the word "flat" in it
proc sql noprint;
select distinct libname
, count(libname)
into: tbl_list separated by ' '
, total_tbls
from sashelp.vmember
where libname LIKE 'FLAT%'
;
quit;
This will create two macro variables: &tbl_list, and &total_tbls.
&tbl_list holds the values flat0113 flat0213 flat ... flat1213.
&total_tbls holds the total number of values in &tbl_list.
Step 2: Loop through the newly created list
%macro readTables;
%do i = 1 %to &total_tbls;
%let tbl = %scan(tbl_list, &i);
proc sql exec feedback stimer noprint outobs=5;
CREATE TABLE &tbl as
SELECT
ID,
DOB,
"&tbl" as Table_Dt
FROM &tbl..flat_file;
quit;
%end;
%mend;
%readTables;
This will read each individual value from &tbl_list one by one until the very end of the list.
I hope someone can help. I have a large dataset imported to SAS with thousands of variables. I want to create a new dataset by extracting variables that have a specific keyword in their name. For example, the following variables are in my dataset:
AAYAN_KK_Equity_Ask
AAYAN_KK_Equity_Bid
AAYAN_KK_Equity_Close
AAYAN_KK_Equity_Date
AAYAN_KK_Equity_Volume
AAYANRE_KK_Equity_Ask
AAYANRE_KK_Equity_Bid
AAYANRE_KK_Equity_Close
AAYANRE_KK_Equity_Date
I want to extract variables that end with _Ask and _Bid without knowing the rest of the variable's name. Is there a way to do that? I want to try using a do loop but don't know how to instruct SAS to compare each variable's last part of the name with _Ask or _Bid.
Afterwords. I want to create a new variable for each set that starts with full name of the variable except the last part (Which is _Ask or _Bid). Can I do that in using an assignment statement?
You probably want to query sashelp.vtable which holds the metadata about your data set. Assuming your data is in the library WORK and called TABLE the following creates a list of the variables that end in ASK.
proc sql;
select name into :varlist separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
*To rename the variables with MID generate a rename statement;
proc sql;
select catx("=", name, tranwrd(upcase(name), "_ASK", "_MID"))
into :rename_list separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
%put &rename_list;
data want_ask;
set work.table
(keep = &varlist);
rename &rename_list;
run;
I have a set of datasets which I would like to output in an Excel File. Is there a way to do this quickly rather than calling proc export each time for each dataset
%let MyDS = ('out.Ids', 'out.Vars', 'out.Places')
%let MyDSname = (Ids, Vars, Places)
I would like to create a macro that check if each dataset exists and then output to an Excel spreadsheet with the Tab name as specified in the corresponding MyDSname ...
Something like... %macro Out(MySpreadsheetName, MyDS, MyDSname);
Thanks very much for your help
Assuming you have Access to PC Files licensed, the easiest way to do this (export several datasets to one workbook) is with a libname.
libname mywbk excel 'c:\pathtomyexcel\excelfile.xlsx';
data mywbk.nameoftab;
set dataset;
run;
In terms of conditionally creating this, you should look at how you're arriving at the list of names to export. In general, you should have a dataset that contains one row per dataset to export, and two columns - DS name and tab name. You can then merge that to sashelp.vtables or dictionary.tables which are views containing the list of tables in the current SAS session; memname is the name of the table, libname is the name of the library. Then create a macro call from that:
proc sql;
select cats('%out(',dsname,',',tabname,')') into :calllist separated by ' '
from joinedds;
quit;
libname ... ;
&calllist.;