I am attempting to read in many files of data including a column of datetimes. When I read in all of the files, the datetime column contains the same date everywhere (31 JUL 2015 00:00:00, or in SAS format: 1753920000) even though the data files being read in have many different datetimes in that column. Why would my code be outputting the same date for every row?
Code:
%let type=40;
%let year=2015;
%let months =07;
%let days = 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31;
%let filetype=.csv;
%macro import_files;
%do K=1 %to 31; /*day*/
%let nmbr = %scan(&type,1);
%let yr=%scan(&year,1);
%let mnth=%scan(&months,1);
%let day=%scan(&days,&K);
%let exportfile = "C:\Users\Top&nmbr&yr&mnth&day&filetype";
%let src = "\\2119\outfile";
/* Import All files in that Alpha, Year and Month Group*/
DATA work.RAW_DATA;
INFILE &src firstobs=3 LRECL=1000 DELIMITER=',' MISSOVER DSD;
INPUT city_cd : $CHAR3.
shop_car_type_cd : $CHAR4.
lor: ?? BEST2.
arv_dt : ?? MMDDYY10.
shop_dttm : ?? ANYDTDTM19. /* This is the datetime that reads in the same date for every observation */
RUN;
%end;
%mend import_files;
%import_files;
CSV datafile:
ATL CCAR 1 10:30 9/7/2015 01JUL2015:00:00:00
After reading into SAS:
ATL CCAR 1 37800 20338 1751500800
Unless I'm missing something serious, you have 5 variables listed on your INPUT statement but 6 in your sample data. Which one is correct? I would also switch the MISSOVER to TRUNCOVER, . Additionally consider specifying an informat for your variables instead of how you're trying to read it. You're not getting any errors because of the ?? which suppresses any errors. Remove them from your code. I'll post an answer below to help you get started but it's not likely correct.
As mentioned, you also do not have a CSV file unless you copied and pasted from an Excel file, which you shouldn't do. Excel may be adding/stripping something from your data that we can't see which can cause the issues.
data have;
informat arv_dt mmddyy10. shop_dttm anydtdtm. time_data time.;
format shop_dttm datetime21. time_data time.;
INPUT
city_cd $
shop_car_type_cd $
lor
time_data
arv_dt
shop_dttm;
cards;
ATL CCAR 1 10:30 9/7/2015 01JUL2015:00:00:00
;
run;
proc print data=have;
run;
Related
I have a dataset as listed below:
ID-----V1-----V2------V3
01------5------3-------7
02------3------8-------5
03------6------9-------1
and I want to calculate 3 new variables (ERR_CODE, ERR_DETAIL, ERR_ID) according to behavior of certain columns.
If V1 is greater than 4 then ERR_CODE = A and ERR_DETAIL = "Out of range" and ERR_ID = [ID]_A
If V2 is greater than 4 then ERR_CODE = B and ERR_DETAIL = "Check Log" and ERR_ID = [ID]_B
If V3 is greater than 4 then ERR_CODE = C and ERR_DETAIL = "Fault" and ERR_ID = [ID]_C
Desired output table be like
ID-----ERR_CODE----ERR_DETAIL---------ERR_ID
01--------A--------Out of range---------01_A
01--------C--------Fault----------------01_C
02--------B--------Check Log------------02_B
02--------C--------Fault----------------02_C
03--------A--------Out of range---------03_A
03--------B--------Check Log------------03_B
I am using SAS 9.3 with EG 5.1. I have tried do-loops, arrays, if statements and case-when's but it naturally skips to the next row to calculate when condition is met. But i want to calculate other met conditions fo each row.
I have managed to do it by creating seperate tables for each condition and then merge them. But that doesn't seem an effective way if there are much conditions to work with.
My question is how can i manage to calculate other met conditions for each ID at once without calculating seperately? The output table's row count will be more than the input as expected but for me it is not possible to achieve by applying case-when or if etc.
Thanks in advance and sorry if i am not clear.
Just use IF/THEN/DO blocks. Add an OUTPUT statement to write new observation for each error.
data have ;
input ID $ V1-V3;
cards;
01 5 3 7
02 3 8 5
03 6 9 1
;
data want;
set have;
length ERR_CODE $1 ERR_DETAIL $20 ERR_ID $10 ;
if v1>4 then do;
err_code='A'; err_detail="Out of range"; err_id=catx('_',id,err_code);
output;
end;
if v2>4 then do;
err_code='B'; err_detail="Fault"; err_id=catx('_',id,err_code);
output;
end;
if v3>4 then do;
err_code='C'; err_detail="Check Log"; err_id=catx('_',id,err_code);
output;
end;
drop v1-v3 ;
run;
Results:
Obs ID ERR_CODE ERR_DETAIL ERR_ID
1 01 A Out of range 01_A
2 01 C Check Log 01_C
3 02 B Fault 02_B
4 02 C Check Log 02_C
5 03 A Out of range 03_A
6 03 B Fault 03_B
I have a table (EM_UPLOAD) that I've created that I want to update values on in another table (QUESTVAR_CASEITEM). The values in the QUESTVAR table are null and I'm making them not null. I'm attempting to do this with the following code:
PROC SQL;
UPDATE CD1PROD.QUESTVAR_CASEITEM a
SET a.DEBIT_ENTRYMODE=(SELECT EM
FROM EM_UPLOAD b
WHERE A.SEQCASEITEM = B.CASEITEM)
WHERE SEQCASEITEM IN (SELECT CASEITEM FROM EM_UPLOAD);
QUIT;
It keeps erroring out on the SET line saying it's expecting an = when an = is already there...
The log dump is as follows:
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='EM_UPDATE_TESTING';
4 %LET _CLIENTPROCESSFLOWNAME='Process Flow';
5 %LET _CLIENTPROJECTPATH='';
6 %LET _CLIENTPROJECTPATHHOST='';
7 %LET _CLIENTPROJECTNAME='';
8 %LET _SASPROGRAMFILE='[REDACTED]';
9 %LET _SASPROGRAMFILEHOST='W7LT110183466';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=PNG;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 FILENAME EGSR TEMP;
15 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
16 STYLE=HTMLBlue
17 STYLESHEET=(URL="file:///C:/Program%20Files%20(x86)/SAS94/x86/SASEnterpriseGuide/7.1/Styles/HTMLBlue.css")
18 NOGTITLE
19 NOGFOOTNOTE
20 GPATH=&sasworklocation
21 ENCODING=UTF8
22 options(rolap="on")
23 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
24
25 GOPTIONS ACCESSIBLE;
26 LIBNAME CD1PROD SQLSVR USER='XXXXXXXXXXXXXX' PASSWORD=XXXXXXXXXX DSN=STGRAMIHQSQLF18adjhub SCHEMA=DBO QUALIFIER=AdjHub;
NOTE: Libref CD1PROD was successfully assigned as follows:
Engine: SQLSVR
Physical Name: STGRAMIHQSQLF18adjhub
27 /*Update EM field in LEAN*/
28 PROC SQL;
29 UPDATE CD1PROD.QUESTVAR_CASEITEM as a
30 SET A.DEBIT_ENTRYMODE = (SELECT EM
_
73
76
ERROR 73-322: Expecting an =.
ERROR 76-322: Syntax error, statement will be ignored.
31 FROM EM_UPLOAD as b
32 WHERE a.SEQCASEITEM = b.caseitem)
33 WHERE SEQCASEITEM IN (SELECT caseitem FROM EM_UPLOAD);
NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
34 QUIT;
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
35
36 GOPTIONS NOACCESSIBLE;
37 %LET _CLIENTTASKLABEL=;
38 %LET _CLIENTPROCESSFLOWNAME=;
39 %LET _CLIENTPROJECTPATH=;
2 The SAS System 15:33 Monday, January 25, 2021
40 %LET _CLIENTPROJECTPATHHOST=;
41 %LET _CLIENTPROJECTNAME=;
42 %LET _SASPROGRAMFILE=;
43 %LET _SASPROGRAMFILEHOST=;
44
45 ;*';*";*/;quit;run;
46 ODS _ALL_ CLOSE;
47
48
49 QUIT; RUN;
50
Try removing the alias from the target variable name. You can only update variables in a single dataset so perhaps it is confusing things.
... SET DEBIT_ENTRYMODE= ...
Unless EM_UPLOAD only has one observation you probably want to modify the WHERE clause of your UPDATE statement.
WHERE SEQCASEITEM IN (SELECT CASEITEM FROM EM_UPLOAD);
I have a text file where two different columns are having the same name. As shown in the following figure.
Let's say for SystBP, I need to change the first SystBP to SystBP_B and the second SystBP to SystBP_E.
Could someone kindly offer me some help on this?
When programming in SAS Base You should sometimes not expect SAS to read column names from a text file and interpret them as variable names.
You have to instruct SAS what the first data row is, where the values are written and how they should be interpreted (text, number, date, ...) You do that with an infile and an input statement in a data step.
As you write the code yourself, you have complete control.
data READ_FROM_TXT;
infile "C:\myFolder\myFile.txt" firstobs=3 truncover;
* firstobs=3 makes SAS skip the first 2 observations;
* truncover avoids jumping to the next line when the last variable is missing or too short ;
input
#01 ID 2.
#05 Week 4.
#11 SystBP_B 6.
#19 DiastBP_B 6.
...
#41 SystBP_E 6.
#49 DiastBP_E 6.
...
;
* #11 SystBP_B 6. instructs SAS to interpret positions 11 to 16 as a number
* and assign the value to variable SystBP_B;
run;
As you inserted the data as an image, not as text, using markup, I had to guess the positions, so you will have to correct them.
I would make timing into observations.
data test;
infile cards4 firstobs=2;
input id :$8. week #;
do time = 'STR','END';
input SystBP DiastBP Pulse Stress #;
output;
end;
cards;
ID Week SystBP DiastBP Pulse Stress SystBP DiastBP Pulse Stress
1 1 134 44 66 5.8 134 44 66 5.8
;;;;
run;
The INFILE option FIRSTOBS= will let you INPUT the data starting in row 3.
Data file: C:\temp\bp-survey.txt
Start End
ID Week SystBP DiastBP Pulse Stress SystBP DiastBP Pulse Stress
1 1 134 44 66 5.8 134 44 66 5.8
...
Program
filename survey 'c:\temp\bp-survey.txt';
data want;
infile survey firstobs=3;
input
ID Week
SystBP_start DiastBP_start Pulse_start Stress_start
SystBP_end DiastBP_end Pulse_end Stress_end
;
run;
ods html ;
proc print data=want;
run;
I am looking to run the below code, to generate a monthly sequence macro. The below macro brings the sum of CASH_2PLUS and BALS_2PLUS by joining monthly files from the data table.
%macro codegen(yymm);
%local month i ;
%let month=%sysfunc(inputn(&yymm.01,yymmdd8));
PROC SQL;
CREATE TABLE TEAM_PERF_%sysfunc(intnx(month,&month,0),yymmn6) AS
SELECT SUM(A.CASH_2PLUS) AS count_accts_0
%do i=1 %to 11 ;
,SUM(x&i..CASH_2PLUS) AS count_accts_&i
%end;
FROM data.cash_v1_%sysfunc(intnx(month,&month,0),yymmn6) A
%do i=1 %to 11 ;
LEFT JOIN data.cash_v1_%sysfunc(intnx(month,&month,&i),yymmn6) x&i
ON (A.HDR_ACCOUNT_ID= x&i..HDR_ACCOUNT_ID)
%end;
;
QUIT;
%mend codegen ;
%codegen (201612)
My results when I run the above script looks like this
count_accts_0 count_accts_1 count_accts_2 .......count_accts_10 count_accts_11
2004 1984 1975 1543 1448
I want the next sequence to add a record under this :
count_accts_0 count_accts_1 count_accts_2 .......count_accts_10 count_accts_11
2011 1999 1954 1512 -
The next sequence
count_accts_0 count_accts_1 count_accts_2 .......count_accts_10 count_accts_11
2043 2002 1999 - -
.
.
.
.
count_accts_0 count_accts_1 count_accts_2 .......count_accts_10 count_accts_11
2078 - - - -
If I call the macro in sequence e.g. %codegen(201701) and so on till 201711 then I need the %do loop to run in decrement (e.g. 1 to 10 , 1 to 9 ...so on till it reaches 1). Basically, I am trying to work out a sequence where the %codegen(yyyymm) increases by a month while the %do loop reduce by 1.
I am a beginner trying to learn.
I asking an old question. I have the code and have looked to previous questions but nevertheless I am unable to correct my mistake. Below is the code with dummy data. I am unable to pass the names of variables to the macro.
data x;
inputs x$ y z;
datalines;
a 23 34
b 34 43
a 23 54
b 87 78
a 12 32
b 22 33
;
run;
Now I create a list of variables
%let name_list=y z;
Then I write macro.
%macro mixed;
%let j=1;
%let first=%scan(&name_list.,%eval(&j));
%do %while (&first ne );
proc mixed data=x;
class x;
model &name_list.=;
random x;
ods output covParms=cov1;
run;
%let j=%eval(&j+1);
%let first=%scan(&name_list.,%eval(&j));
%end;
run;
%mend;
%mixed;
Some how this is not working. Any help will be appreciated.
If you want to iterate over the names in a list then you can just use a normal %DO ... %TO loop. No need to manually initialize or increment the counter.
%do i=1 %to %sysfunc(countw(&name_list));
%let name=%scan(&name_list,&i);
.... place code here that uses &NAME ....
%end;