BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
smcconn5
Calcite | Level 5

Hello,

 

I have a large data set with customer IDs and daily cumulative usage readings. I'm looking to calculate the daily usage per customer from the cumulative usage and add it as a variable in the data set. Any suggestions on how to even begin doing this? Thank you!

 

HAVE
ID     date     cumulative_reading     
1     10/1/19     100
1     10/2/19     150
1     10/3/19     200
2     10/1/19     100
2     10/2/19     500
2     10/3/19     900



WANT
ID     Date     Cumulative_reading     Daily Usage
1     10/1/19      100                          50
1     10/2/19      150                          50
1     10/3/19      200                              
2     10/1/19      100                          400
2     10/2/19      500                          400
2     10/3/19      900

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Much easier if you put the value on the current record instead of the previous one.

data want;
  set have ;
  by id ;
  daily_usage=dif(cumulative_reading);
  if first.id then daily_usage=.;
run;

Results:

                           cumulative_    daily_
Obs    id          date      reading       usage

 1     1     2019-10-01        100            .
 2     1     2019-10-02        150           50
 3     1     2019-10-03        200           50
 4     2     2019-10-01        100            .
 5     2     2019-10-02        500          400
 6     2     2019-10-03        900          400

You can even decide if you want the first record's value to be missing or set it to the first value.

  if first.id then daily_usage=cumulative_reading;

Results:

                           cumulative_    daily_
Obs    id          date      reading       usage

 1     1     2019-10-01        100          100
 2     1     2019-10-02        150           50
 3     1     2019-10-03        200           50
 4     2     2019-10-01        100          100
 5     2     2019-10-02        500          400
 6     2     2019-10-03        900          400

View solution in original post

3 REPLIES 3
PaigeMiller
Diamond | Level 26
data want;
    set have;
    by id;
    prev_cumulative=lag(cumulative_reading);
    if first.id then daily=cumulative_reading;
    else daily=cumulative_reading-prev_cumulative;
    drop prev_cumulative;
run;

This assumes the data is properly sorted.

 

Also, you might want to re-think your example, there is no logical way to get a daily of 50 for the first row. 

--
Paige Miller
Tom
Super User Tom
Super User

Much easier if you put the value on the current record instead of the previous one.

data want;
  set have ;
  by id ;
  daily_usage=dif(cumulative_reading);
  if first.id then daily_usage=.;
run;

Results:

                           cumulative_    daily_
Obs    id          date      reading       usage

 1     1     2019-10-01        100            .
 2     1     2019-10-02        150           50
 3     1     2019-10-03        200           50
 4     2     2019-10-01        100            .
 5     2     2019-10-02        500          400
 6     2     2019-10-03        900          400

You can even decide if you want the first record's value to be missing or set it to the first value.

  if first.id then daily_usage=cumulative_reading;

Results:

                           cumulative_    daily_
Obs    id          date      reading       usage

 1     1     2019-10-01        100          100
 2     1     2019-10-02        150           50
 3     1     2019-10-03        200           50
 4     2     2019-10-01        100          100
 5     2     2019-10-02        500          400
 6     2     2019-10-03        900          400
Kurt_Bremser
Super User

You need to do a "look-ahead":

data have;
input ID date :mmddyy10. cumulative_reading;
format date yymmddd10.;
datalines; 
1     10/1/19     100
1     10/2/19     150
1     10/3/19     200
2     10/1/19     100
2     10/2/19     500
2     10/3/19     900
;

options mergenoby=nowarn;

data want;
merge
  have
  have (
    firstobs=2
    keep=id cumulative_reading
    rename=(id=nextid cumulative_reading=nextval)
  )
;
if id = nextid then daily_usage = nextval - cumulative_reading;
drop nextid nextval;
run;

proc print data=want noobs;
run;

Result:

                    cumulative_    daily_
ID          date      reading       usage

 1    2019-10-01        100           50 
 1    2019-10-02        150           50 
 1    2019-10-03        200            . 
 2    2019-10-01        100          400 
 2    2019-10-02        500          400 
 2    2019-10-03        900            . 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 496 views
  • 2 likes
  • 4 in conversation