SAS issue with Rename variable - sas

I have a dataset with 6 character variables including Day5,Day6,Day7,City1,City2,City3.
I am trying to rename Day5 which was extracted as i__Day5 after importing txt file into SAS. The variable i__day5 is not getting renamed to day5 and so it does not shows any observation for this variable.
data subset ;
set subset ;
rename i__Day5 = Day5;
run;
Thanks.

As Tom mentioned your problem likely stems from overwriting the original table with the modified data, and then trying to submit your code to run again.
It will work the first time when the variable i__Day5 exists, but on running it a second time, the variable will no longer exist as it has already been renamed.
To avoid this issue never re-use table names. This code would be better:
data subset2 ;
set subset ;
rename i__Day5 = Day5;
run;
Space is cheap so there's no real downside to doing this, plus it gives you an easy way to compare the table before/after running the code.
The only other issue that this could be is that you are viewing field labels and not field names. As samkart mentions, you can verify the actual field names by running a proc contents against your table.

Related

Variable has never been referenced [SAS]

I have a dataset containing information by an account number. I'm trying to add a new variable, called product_type, populated with the same value for every record. It is within a SAS macro.
data CC_database;
set cc_base_v2 (keep=accnum date product_type);
product_type="CC";
where date>=%sysevalf("&start_date."d) and file_date<=%sysevalf("&end_date."d);
run;
However, I keep getting the error "The variable product_type has in the DROP, KEEP, or RENAME list has never been referenced" and the output dataset only shows a blank column called product_type. What is happening here?
You are using the KEEP= dataset option on the input dataset. So the error is saying PRODUCT_TYPE does not exist in the dataset CC_BASE_V2.
If you want to control what variables are written by the data step just use a KEEP statement.
keep accnum date product_type;
In your case you could use the KEEP= dataset option but only list the variables taht are coming from CC_BASE_V2.
data CC_database;
set cc_base_v2(keep=accnum date file_date);
where date>= "&start_date."d and file_date<="&end_date."d;
product_type="CC";
drop file_date;
run;

Difficulty understanding the "_n_" variable in SAS, and how it applies to a concatenate function

I am very new to SAS, and for whatever reason am finding a lot of difficulty deciphering what this code block (below) does. I've googled and search stackoverflow to no avail. I'd appreciate any input, thanks!
set dataset;
id=cat("L",_n_);
run;
Probably there must be a data statement as well.
data newdataset;
set dataset;
id = cat("L", _n_);
run;
This above code creates a new dataset named newdataset from the existing dataset named dataset.
Also creating a new column called id, and id is creating by concatenating a constant character value "L" with the automatic variable _n_ using the CAT function. The automatic variable _n_ represents the number of times the DATA step has iterated.

How to accumulate the records of a newly imported table with the records of another table that I have stored on the servers in SAS?

I am new to SAS and I have the following problem:
When trying to join records I just imported (in one table) with records I have stored in another table.
What happens is that I am going to run the code in SAS daily, and I need the table that I am going to create today (17/05/2021) by importing a file 'X', to join the table that I created yesterday (16/05/2021) by importing a file 'Y'.
And so the code will be executed tomorrow, the next day and so on.
In conclusion the records will accumulate as the days go by.
To tackle this problem, I am first creating two variables, one with the date of the day the code will be executed and the other with the date of the last execution.
%let daily_date = 20210423; /*AAAAMMDD*/
%let last_execution_date = 20210422; /*AAAAMMDD*/
Then the import of a file is done, we can see that the name of this created table has the date of the day in which the code is being executed.
data InputAC.RA_ratings&daily_date;
infile "&ruta_InputRA." FIRSTOBS=2
dsd lrecl=4096 truncover;
input
#1 RA_Customer_ID $10.
#11 Rating_ID 10.
#21 ISRM_Model_Overlay_ID $10.
#31 Constant_ID 10.
#41 Value $100.
;
run;
proc sort data=inputac.RA_ratings&daily_date;
by RA_Customer_ID Rating_ID;
quit;
Finally the union of InputAC.RA_ratings&daily_date with InputAC.RA_ratings&last_execution_date is made. ('InputAC.RA_ratings&last_execution_date' should be the table that was imported at an earlier date than today.)
data InputAC.RA_ratings&fec_diario;
merge
InputAC.RA_ratings&fec_diario
InputAC.RA_ratings&ultima_fecha_de_ejecucion;
by RA_Customer_ID Rating_ID;
run;
This is how the tables are being stored on the server.
(Ignore date 20210413, let's imagine it is 20210422)
However, I have to perform this task without using the variable 'last_execution_date'.
I've been researching but I still can't find any SAS function that can help me with this problem.
I hope someone can help me, thank you very much in advance.
This is a pretty complex and interesting question from an operations point of view. The answer depends on a few things.
How much control do you have over the execution of this process?
Is "yesterday" guaranteed, or does the process need to work if "last execution date" is not yesterday?
What should happen if the process is run twice today?
The best practices way to solve this is to have a dataset (or table) that stores the last execution date. That allows you to handle #2 trivially, and the answer to #3 might guide exactly how you store this but is easily handled anyway.
Say for example you have a table, MetaAC.LastExecDate (or, in spanish, MetaAC.UltimaFecha or similar). It could store things this way:
data LastExecDate;
timestamp = datetime();
execdate = input(&daily_date,yymmdd8.);
run;
proc append base=MetaAC.LastExecDate data=LastExecDate;
run;
This lets you store an arbitrary execdate even if it's not today, and also store when you ran it (for audit purposes), and you could even add who ran it if that's interesting (there is a macro variable &sysuserid or similar). Then put all this at the bottom of your process, and it updates as you go.
Then, you can pull out from this the exact info you want - for example,
proc sql;
select max(execdate)
into :last_exec_date
from MetaAC.LastExecDate
where execdate ne today()
;
quit;
Now, if you don't have control over this for some reason, you could determine this in a different way. Again, the exact process depends on your circumstances and your answers to 2 and 3.
If your answer to 2 is you always want it to be yesterday, then this is really easy - just do this:
%let daily_date=20210517;
%let last_execution_date = %sysfunc(putn(%sysevalf(%sysfunc(inputn(&daily_date,yymmdd8.))-1),yymmddn8.));
%put &=last_execution_date;
The two %sysfuncs just do the input/put from SAS datastep inside the macro language, and %sysevalf lets you do math.
If you don't want it to always be the prior day (if there are weekends, or other days you don't necessarily want to assume it's the prior day), then your best bet is to either use the dictionary tables to look at what's there and find the largest date prior to your date, or maybe use a x command to look at the folder and do the same thing (might be easier to use OS command than to use SQL for this, sometimes SQL dictionary tables can be slow).

SAS: Naming a table based on a cell value

I have an Excel file that always has the same name but the contents of the table changes. I am looking to write a code that names the table based on the value in one of the cells.
For example:
If cell A3 equals "Employment Information", I want the table to be named "Jobs".
If cell A3 equals "Inflation Information", I want the table to be named "Currency".
etc.
I want to define ONE macro (i.e. %table(filename,cell)), or ONE loop of if then else statements to achieve this. Unfortunately, I can't seem to wrap my head around this logically. If someone with experience in SAS could help me out that would be awesome. I will edit my question soon to include some codes that I have already tried but which have failed to get the job done.
You need to read the data to find the content. You could then create a macro variable to make it easy to rename the dataset using PROC DATASETS.
Let's assume you have converted the Excel sheet into a dataset named WORK.HAVE. Let's also assume that you know what variable contains the data from column A, let's call that variable A. Is there anything in the data that makes it possible to tell which observation is the one to use? For now let's just assume that by A3 you mean the second observation since the first row of the sheet should have the variable names.
So in that case you want something like this:
%let newname=have;
data _null_;
set have (firstobs=2);
if A="Employment Information" then call symputx('newname','Jobs');
else if A="Inflation Information" then call symputx('newname','Currency');
stop;
run;
proc datasets nolist lib=work;
change have=&newname;
run;
quit;

Change variable length in SAS dataset

I need to change the variable length in a existing dataset. I can change the format and informat but not the length. I get an error. The documentation says this is possible but there are no examples.
Here is my issue. My data source could change so I don't want to pre define columns on import. I want to do a generic import and then look for certain columns and adjust the length.
I have tried PROC SQL and DATA steps. It looks like the only way to do this is to recreate the dataset or the column. Which I don't want to do.
Thanks,
Donnie
If you put your LENGTH statement before the SET statement, in a Data step, you can change the length of a variable. Obviously, you will get truncation if you have data longer than your new length.
However, using a DATA step to change the length is also re-creating the data set, so I'm confused by that part of your question.
The only way to change the length of a variable in a datastep is to define it before a source (SET) dataset is read in.
Conversely you can use an alter statement in a proc sql. SAS support alter statement
Length of a variable remains same once you set the dataset. Add length statements before you set the dataset if you need to change length of a columns
data a;
length a, b, c $200 ;
set b ;
run ;