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

Hello

If the value is equal to 12 in the qty column then I need to divide the qty column to the MinQ column. The result will be spreading in the desired output until the total qty for each dest id between the March 3 and March 12 is equal the sum of If the desired value.  If the qty is not equal 12, then I will keep the same value in the desired output. 

For example, dest id is 13827 and qty is 12 on March 8 and the desired output will start from March 8 as 4 pcs and keep continue until March 10 as 4 pcs so the total of the desired value  12 

The other example, if 12 in the qty column comes at the end of the dest id then the output has to be spread out earlier than March 12

For example, Dest id is 15007. There are two 12 inputs in different place of the qty column and the one is in the middle and the other one is at the end of the column so the 12 which is at the end of the column should start earlier March 10 because they have to refer 15007 Dest id. Thank you for your help

 

Input    
dest_iditemScheduledArrivalDateqtyMinQ
1382740000303Mar201903
1382740000304Mar201903
1382740000305Mar201903
1382740000306Mar201903
1382740000307Mar201903
1382740000308Mar2019123
1382740000309Mar201903
1382740000310Mar201903
1382740000311Mar201903
1382740000312Mar201903
1500740000303Mar201903
1500740000304Mar201903
1500740000305Mar2019123
1500740000306Mar201903
1500740000307Mar201903
1500740000308Mar201903
1500740000309Mar201903
1500740000310Mar201903
1500740000311Mar201903
1500740000312Mar2019123

 

 

Desired Output    
dest_iditemScheduledArrivalDateqtyMinQDesired Output
1382740000303Mar2019030
1382740000304Mar2019030
1382740000305Mar2019030
1382740000306Mar2019030
1382740000307Mar2019030
1382740000308Mar20191234
1382740000309Mar2019034
1382740000310Mar2019034
1382740000311Mar2019030
1382740000312Mar2019030
1500740000303Mar2019030
1500740000304Mar2019030
1500740000305Mar20191234
1500740000306Mar2019034
1500740000307Mar2019034
1500740000308Mar2019030
1500740000309Mar2019030
1500740000310Mar2019034
1500740000311Mar2019034
1500740000312Mar20191234
1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

To the extent that I understand the problem, here goes.

 

Because of the need to spread both forward and backward, you will need to make several passes through the data.  The first pass:

 

proc sort data=have;
   by dest_id ScheduledArrivalDate;
run;

data first_pass;
   set have;
   by dest_id;
   desired_output = 0;
   if first.dest_id then quantity_to_be_spread = 0;
   if qty = 12 then quantity_to_be_spread + 12;
   if quantity_to_be_spread > 0 then do;
      desired_output = 12 / MinQ;
      quantity_to_be_spread = quantity_to_be_spread - desired_output;
   end;
run;

This spreads the quantities into later dates, but not into earlier dates.  To the extent that some of the spreading has to be done across earlier dates, it takes another pass through the data.

 

proc sort data=first_pass;
   by dest_id descending ScheduledArrivalDate;
run;

data second_pass;
   set first_pass;
   by dest_id;
   if first.dest_id then do;
      quantity_to_be_spread = 0;
      quantity_already_spread = 0;
   end;
   if qty = 12 then quantity_to_be_spread + 12;
   quantity_already_spread + desired_output;
   if quantity_to_be_spread > quantity_already_spread 
   and desired_output = 0 then do;
      desired_output = 12/MinQ;
      quantity_already_spread + desired_output;
   end;
   drop quantity_to_be_spread quantity_already_spread;
run;

Finally, put the data back into its proper order:

proc sort data=second_pass out=want;
   by dest_id ScheduledArrivalDate;
run;

Just a note .... this is untested code.  So you would need to try it and report back any difficulties.  There are definitely some situations within the data that I could imagine that could cause problems.  But this should handle the basic situation as long as the data behaves.

 

View solution in original post

8 REPLIES 8
mkeintz
PROC Star

What you need to do is:

  1. Establish a value for desired_output whenever qty=12
  2. Establish a counter to count down the number of records to have that desired_output value.

And you need a way to keep value #1 above and to count down value 2 as the data step iterates through successive observations.  This can be done by holding the values in retained variables (call them _desoutput  and _counter). I.e., learn about the RETAIN statement.

 

To calculate the retained values when QTY=12, you need an

   if qty=12 then do;

     *** calculate the retained values _desoutput  and _counter ***;

   end;

 

Then all you need to do, for each and every observation, is to test the value of _counter.  If it's a positive number then permanent variable DESIRED_OUTPUT gets the value of _desoutput.  Otherwise it's a zero.  This is a simple

    if ... then ...;

    else ...;

pair of statements.

 

Finally decrement the _counter variable by 1.  It doesn't matter if you decrement it to negative value, since it will become positive again only when needed - i.e. when QTY=12.

 

 

Then, as long as _counter>0 you should assign the value from _desoutput to desired_output (otherwise assign zero).  And be sure to decrement _counter by 1:

 

So the logical structure could be something like

 

 

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
hcbn
Obsidian | Level 7

Can you please write a code for the explanation?

mkeintz
PROC Star

This has all the earmarks of a homework assignment, especially since I see similar new topics.  Since I won't get credit for the homework, I'm only willing to point you in the proper direction.  That's why I suggested the RETAIN statement, and a group of statement to put inside and an "IF QTY=12 then DO; ....... END;" group.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Astounding
PROC Star

To the extent that I understand the problem, here goes.

 

Because of the need to spread both forward and backward, you will need to make several passes through the data.  The first pass:

 

proc sort data=have;
   by dest_id ScheduledArrivalDate;
run;

data first_pass;
   set have;
   by dest_id;
   desired_output = 0;
   if first.dest_id then quantity_to_be_spread = 0;
   if qty = 12 then quantity_to_be_spread + 12;
   if quantity_to_be_spread > 0 then do;
      desired_output = 12 / MinQ;
      quantity_to_be_spread = quantity_to_be_spread - desired_output;
   end;
run;

This spreads the quantities into later dates, but not into earlier dates.  To the extent that some of the spreading has to be done across earlier dates, it takes another pass through the data.

 

proc sort data=first_pass;
   by dest_id descending ScheduledArrivalDate;
run;

data second_pass;
   set first_pass;
   by dest_id;
   if first.dest_id then do;
      quantity_to_be_spread = 0;
      quantity_already_spread = 0;
   end;
   if qty = 12 then quantity_to_be_spread + 12;
   quantity_already_spread + desired_output;
   if quantity_to_be_spread > quantity_already_spread 
   and desired_output = 0 then do;
      desired_output = 12/MinQ;
      quantity_already_spread + desired_output;
   end;
   drop quantity_to_be_spread quantity_already_spread;
run;

Finally, put the data back into its proper order:

proc sort data=second_pass out=want;
   by dest_id ScheduledArrivalDate;
run;

Just a note .... this is untested code.  So you would need to try it and report back any difficulties.  There are definitely some situations within the data that I could imagine that could cause problems.  But this should handle the basic situation as long as the data behaves.

 

hcbn
Obsidian | Level 7

@Astounding  Thank you so much. I will try and let you know the result. Thank you so much not ignoring my message

hcbn
Obsidian | Level 7

@Astounding 

 

Again, thank you so much for your time and energy you put.

The codes are mostly working . There is only one part that does not work.

Please, look at Dest id 13827 corresponding March 22,19 . It only produced two 4 values but it is necessary to be produced three 4 values. Would you please advise if there is anything to correct this part?

 

run_datedest_iditemScheduledArrivalDateqtyMinqdesired_output
01Mar20191382740000303Mar2019030
01Mar20191382740000304Mar2019030
01Mar20191382740000305Mar2019030
01Mar20191382740000306Mar2019030
01Mar20191382740000307Mar2019030
01Mar20191382740000308Mar20191234
01Mar20191382740000309Mar2019034
01Mar20191382740000310Mar2019034
01Mar20191382740000311Mar2019030
01Mar20191382740000312Mar2019030
01Mar20191382740000313Mar2019030
01Mar20191382740000314Mar2019030
01Mar20191382740000315Mar20191234
01Mar20191382740000316Mar2019034
01Mar20191382740000317Mar2019034
01Mar20191382740000318Mar2019030
01Mar20191382740000319Mar2019030
01Mar20191382740000320Mar2019030
01Mar20191382740000321Mar2019030
01Mar20191382740000322Mar20191234
01Mar20191382740000323Mar2019034
01Mar20191500740000303Mar2019020
01Mar20191500740000304Mar2019020
01Mar20191500740000305Mar2019020
01Mar20191500740000306Mar2019020
01Mar20191500740000307Mar2019020
01Mar20191500740000308Mar20191226
01Mar20191500740000309Mar2019026
01Mar20191500740000310Mar2019020
01Mar20191500740000311Mar2019020
01Mar20191500740000312Mar2019020
01Mar20191500740000313Mar2019020
01Mar20191500740000314Mar2019020
01Mar20191500740000315Mar2019020
01Mar20191500740000316Mar2019020
01Mar20191500740000317Mar2019020
01Mar20191500740000318Mar2019020
01Mar20191500740000319Mar2019020
01Mar20191500740000320Mar2019020
01Mar20191500740000321Mar2019020
01Mar20191500740000322Mar20191226
01Mar20191500740000323Mar2019026
Astounding
PROC Star

Please post the log as well, so I can confirm the code that actually ran.  I will be able to take a look later in the day.

 

Also, double-check to make sure you are looking at the right data set.  The data you posted is what I would expect FIRST_PASS to look like.

ballardw
Super User

@hcbn wrote:

Hello

If the value is equal to 12 in the qty column then I need to divide the qty column to the MinQ column. The result will be spreading in the desired output until the total qty for each dest id between the March 3 and March 12 is equal the sum of If the desired value.  If the qty is not equal 12, then I will keep the same value in the desired output. 

 

You have posted six  (or more) topics on minor variations of the same problem, with subject lines that do not clearly differentiate the differences.

 

I am wondering if perhaps you might be in a "forest for the trees" situation where you are attempting to solve little bits of a bigger problem and possibly introducing a lot of other work. I was trying to determine what any of these data sets might be used for and not really coming up with an actual real world use. So if these are not hypothetical "just to learn programming" questions perhaps you can describe what the resulting data sets are actually used for after they are made.

 

I ask because in the past we have seen similar types of related questions and found someone was attempting to manually do all the steps that other procedures do in the back ground such as Proc Report or Tabulate summarizing and grouping for displays or duplicating one of the Regression procedures.

 

PS: By now you should know to post example data in the form of a data step and in one of the code boxes opened with either the {I} or "running man" Icon.

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!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 8 replies
  • 872 views
  • 0 likes
  • 4 in conversation