BookmarkSubscribeRSS Feed
M_96
Calcite | Level 5

Hello,

I have a subset of dates and values of sales. For each data and for each point of sale, I need to sum the sales of the previous six months. The column Sellin is what I expect to have.

Example for the PV 9097947:

(dates are in Italian format)

PVdatasale $Sell-in
909794718/01/2023        8.400\
909794708/02/2023        7.200\
909794724/02/2023        6.750\
909794710/03/2023        7.800\
909794729/03/2023      10.575\
909794719/04/2023      10.875\
909794708/05/2023        3.750\
909794722/05/2023        9.000\
909794708/06/2023      10.950\
909794728/06/2023        9.75075300
909794720/07/20231095076650

What program can fit better what I need? I think a do loop but I don't know how to do it.

 

Thanks

8 REPLIES 8
Kurt_Bremser
Super User

Use a date-indexed array:

%let start = %sysfunc(inputn(1900-01-01,yymmdd10.));
%let end = %sysfunc(inputn(2099-12-31,yymmdd10.));

data want;
set have;
by pv;
array s {&start.:&end.} _temporary_;
if first.pv
then do i = &start. to &end.;
  s{i} = 0;
end;
s{data} = s{data} + sales;
do i = intnx("month",data,-6,"s") to data;
  sales_sum6 = sum(sales_sum6,s{i});
end;
drop i;
run;

Untested, posted from my tablet.

M_96
Calcite | Level 5

WOW, it works. I need two adjustments: the first one is that the sellin doesn't have to consider the sales of the day (so for example, for today it has to consider the sales from yesterday up to 6 months ago) - see the SALES_SUM6 of the last 3 rows of the table;

the other adjustment is that the variable SALES_SUM6 needS to be null if for a given date there isn't a history of at least 6 months (in our case all the dates up to 18AUG2023 need to have SALES_SUM6 null because 18AUG2023 - 180 days is 19FEB2024 and our data starts from 02MAR2023 and it is ok ) - see the first rows of the table.

See the table to understand the 2 adjustments:

PVDATESELLIN6MONTHSAGOSALES_SUM6
201116402-mar-23225003SEP20220
201116422-mar-23232523SEP20220
201116406-apr-23247508OCT20220
201116421-apr-23285023OCT20220
201116405MAY2023247506-nov-220
201116418MAY2023240019-nov-220
201116401JUN2023247503DEC20220
201116415JUN2023217517DEC20220
201116430JUN2023225001JAN20230
201116414JUL2023247515JAN20230
201116428JUL2023210029JAN20230
201116418AUG2023112519-feb-2326250
201116404SEP2023202508-mar-2325125
201116420SEP2023255024-mar-2324825

 

I hope my explanation is clear and there is a solution ofr my requests. Thank you so much! I'm very grateful

Kurt_Bremser
Super User
data want;
set have;
by pv;
array s {&start.:&end.} _temporary_;
if first.pv
then do i = &start. to &end.;
  s{i} = .;
end;
s{data} = sum(s{data},sales);
do i = intnx("month",data,-6,"s") to data - 1;
  sales_sum6 = sum(sales_sum6,s{i});
end;
drop i;
run;

If all array elements are missing, the SUM function will always return a missing value.

 

And if you want to look back 180 days instead of 6 months, replace the INTNX function call with

data - 180

Keep in mind that SAS dates are counts of days.

M_96
Calcite | Level 5

Great! Just one last question. What type of change I need in the code below if I want to calculate for each pv and for each date the mean of the days? It seems to work but the results are wrong.

 

data freq;
set dataset;
by pv;
array s {&start.:&end.} _temporary_;
if first.pv
then do i = &start. to &end.;
s{i} = .;
end;
s{data} = mean(s{data},days);
do i = intnx("day",data,-180,"s") to data - 1;
freq = mean(days,s{i});
end;
format i date9.;
*drop i;
run;

 

Here the sample of data (here mean_days is not correct):

pvdate daysmean_days
201116402-mar-2303SEP2022..
201116422-mar-2323SEP20222010
201116406-apr-2308OCT2022157.5
201116421-apr-2323OCT2022157.5
201116405MAY202306-nov-22147
201116418MAY202319-nov-22136.5
201116401JUN202303DEC2022147
201116415JUN202317DEC2022147
201116430JUN202301JAN2023157.5
201116414JUL202315JAN2023147
201116428JUL202329JAN2023147
201116418AUG202319-feb-232110.5
201116404SEP202308-mar-23178.5

 

Thanks in advance.

M_96
Calcite | Level 5

"Days" are the days between each date of sale and the previous one. I need to understand the average number of days that pass between one sale and another for the PV, still considering the last six months for each date of sale.

Here what I expect to have:

pvdatedate - 180 daysdaysmean_days WRONGmean days CORRECT
201116402-mar-2303-set-220.0
201116422-mar-2323-set-2220100
201116406-apr-2308-ott-22157.510
201116421-apr-2323-ott-22157.511,66666667
201116405-mag-2306-nov-2214712,5
201116418-mag-2319-nov-22136.512,8
201116401-giu-2303-dic-2214712,83333333
201116415-giu-2317-dic-2214713
201116430-giu-2301-gen-23157.513,125
201116414-lug-2315-gen-2314713,33333333
201116428-lug-2329-gen-2314713,4
201116418-ago-2319-feb-232110.513,45454545
201116404-set-2308-mar-23178.515,36363636
201116420-set-2324-mar-2316815,09090909

 

Kurt_Bremser
Super User

I don't get your formula. In observation 3, you would have 2 intervals of 20 and 15 days, giving a mean of (20 + 15) / 2 = 17.5.

You need to create a second array for the intervals:

data want;
set have;
by pv;
array s {&start.:&end.} _temporary_;
array i {&start.:&end.} _temporary_;
_l = dif(data);
if first.pv
then do _i = &start. to &end.;
  s{_i} = .;
  i{_i} = .;
end;
else i{data} = _l;
s{data} = sum(s{data},sales);
_c = 0;
_i_sum = 0;
do _i = data - 180 to data - 1;
  sales_sum6 = sum(sales_sum6,s{_i});
  if i{_i} ne .
  then do;
    _c = _c + 1;
    _i_sum = _i_sum + i{_i};
    mean_days = _i_sum / _c;
end;
drop _i _l _c _i_sum;
run;

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 664 views
  • 2 likes
  • 2 in conversation