I have an Excel sheet of 750,000 rows that span 8 months. I have to display all of the attributes, so Select * would be used. This is SAS Enterprise 9.4.
This is an example of the attributes I'm interested in for the code:
Attribute: Subscriber_Number | Date_Email_Sent
19202 03Dec2020
12829 03Dec2020
13455 05Dec2020
13455 05Dec2020
13455 02 Dec2020
13455 04 Dec2020
An email cannot be sent to a subscriber more than 3 times a week. If that happens, that would become an issue. My goal is to find subscribers who have been called more than 3 times a week. In the example data I gave, the code output should show that Subscriber 13455 was called 4 times in a week. The code output should NOT include 12829 because it just occurs one time.
These are 2 different example codes that I tried and the problems I found with both:
data counts;
set have;
by Subscriber_Number Date_Email_Sent;
counter = dif(Date_Email_Sent) <= 7;
run;
proc summary data=counts; var counter; class Subscriber_Number, output out=sum sum=;
The summary just shows the count all the times a Subscriber was reached out as long as it was less than 7 times, which is not what I'm looking for.
Another Code that I saw that looked promising is this:
PROC SQL; Select week (Date_Email_Sent, 'u') as weeknum, COUNT(Subscriber_Number) as per_week FROM Data; Where SubscriberNumber >2 Group By week(Date_Email_Sent, 'U') quit;
I'm pretty new to SAS, so I'd love help!
The first question: do you count per calendar week, or would you like a running count of mails sent in the last 7 days?
For calendar weeks, this will do it:
data have;
input Subscriber_Number $ Date_Email_Sent :date9.;
format Date_Email_Sent yymmdd10.;
datalines;
19202 03Dec2020
12829 03Dec2020
13455 05Dec2020
13455 05Dec2020
13455 02Dec2020
13455 04Dec2020
;
proc sql;
create table want as
select
*,
count(*) as mails_per_week
from have
group by Subscriber_Number, week(Date_Email_Sent)
having mails_per_week > 3
;
quit;
Note how presenting example data in a data step with datalines clears any ambiguities regarding variable attributes or contents, and makes it easy for everyone else to recreate the dataset as is. Please do so yourself in the future, it speeds up the answering process.
proc sql; create table want as select *, count(*) as mails_per_week from have group by Subscriber_Number, week(Date_Email_Sent) having mails_per_week > 3 ; quit;
Change HAVE to be the name of the data set that already exists.
There are SAS functions that will return week information from a given date and formats that will group data into week intervals when used with analysis procedures.
You have found one of the week functions but Proc SQL may not group things as you would desire as Week returns a number within a year. So if a customer has records in multiple years you would counting all the visits across the years for that week number.
Here is one approach to getting a count using proc summary:
data have; input Subscriber_Number $ Date_Email_Sent date9.; format date_email_sent date9.; datalines; 19202 03Dec2020 12829 03Dec2020 13455 05Dec2020 13455 05Dec2020 13455 02Dec2020 13455 04Dec2020 ; proc summary data=have nway; class Subscriber_Number Date_Email_Sent; format date_email_sent weeku6.; output out=want; run;
When you only have class variables the summary will only have _type_ and _freq_ added to the class variables with _freq_ the count of the particular combination. The NWAY option gives you only the combinations that involve all of the class variables.
The dates in this case, since they are so similar all appear as 20W48. 20 is the last two digits of the year and the W tells you the result is a week in the 48th week of the year. Since we used the Weeku format the week is determined using the U algorithm. These formats if using a width larger than 6 start adding more information such day of week which you wouldn't want for this purpose.
If you want a "prettier" result you could make your own custom format. Example:
proc format; picture myweek (default=9) low-high = '%Y W %0U' (datatype=date) ; run; proc summary data=have nway; class Subscriber_Number Date_Email_Sent; format date_email_sent myweek.; output out=want; run;
The Picture statement directives, the bits preceded by % allow you to display differing date, time or datetime elements. the %0U says to use the U algorithm for calculating week and the zero that precedes the U displays a zero if the week number is a single digit. Other characters, such as the spaces and the W are used literally. So you could replace W with Week to get values of 2020 Week 48 if desired. The Default indicates how many spaces to display by default. Like other formats you can use a width value, such as Myweek12. for different displayed values.
Caution: If you use double quotes around the target string with directives you will nasty messages about macro variables that aren't defined, so this is one place you really want to use single quotes.
Formats used this way will work in the report procedures like Report and Tabulate to group values if want prettier output than Proc Summary.
proc tabulate data=have; class Subscriber_Number Date_Email_Sent ; format date_email_sent myweek.; table Subscriber_Number* Date_Email_Sent , n ; run;
A running count can be achieved by using a temporary array:
%let begin = %sysfunc(inputn(19000101,yymmdd8.));
%let end = %sysfunc(inputn(21001231,yymmdd8.));
proc sort data=have;
by subscriber_number date_email_sent;
run;
data running;
array dates {&begin.:&end.} _temporary_;
set have;
by subscriber_number date_email_sent;
if first.subscriber_number then do i = &begin. to &end.;
dates{i} = .;
end;
count = 0;
dates{date_email_sent} + 1;
do i = date_email_sent - 7 to date_email_sent;
count + dates{i};
end;
if count > 3;
drop i;
run;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.