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

Hi fellow SAS-users!

After much frustration and a lot of reading up on the proc optmodel and examples I turn to you.

Essentially I am trying, by using sets, to read in some data which varies in the number of elements in several dimension. A simplified example of what I want would is:

data Company_Data;

  input Customer Bill;

  datalines;

  cust1 B1

  cust1 B2

  cust1 B3

  cust2 B4

  cust3 B5

  ;

proc optmodel;

set<string> Customers init {};

set<string> Bills{c in Customers};

read data Company_Data into Customers=[customer];

/*Magic to get Bills read into the model */

?

?

?

/*What I want*/

Customers={'cust1','cust2','cust3'};

Bills['cust1'] = {'B1', 'B2', 'B3'};

Bills['cust2'] = {'B4'};

Bills['cust3'] = {'B5'};

/* End of model */

I have tried looking into different constructions of the read into as well as looping over the members of Bills, but unable to get the right data into the model. This feels like a thing that should be fairly easy. Alas I just cannot get it right.

Any thoughts?

1 ACCEPTED SOLUTION

Accepted Solutions
TueChristensen
Calcite | Level 5

The example I showed was just part of bigger program and the parts in question is used to generated sets which I iterate over.

Basically what I am doing is defing the set I and J where J(i \in I).

I will look into if I can use the idea of mapping everything into a set of several string (would be something like set<string,string,string, string> in my case) and then use SetOf to create the indices after reading the data.

Thanks for the reply!

View solution in original post

5 REPLIES 5
user24feb
Barite | Level 11

Shouldn't you have values to read in for proc optmodel? Anyway, maybe this code-snippet is helpful, even though I'm pretty sure, it's not what you are trying to (eventually!) accomplish. 🙂

data Company_Data;
  input Customer $ Bill $ Value;
  datalines;
  cust1 B1 1
  cust1 B2 2
  cust1 B3 3
  cust2 B4 4
  cust3 B5 5
  ;

Proc Optmodel;
  Set <Str,Str> c_b;
  Num Comp_Data{c_b};
  Set Customer =SetOf{<c,b> in c_b} c;
  Set Bill =SetOf{<c,b> in c_b} b;
  Read Data Company_Data into c_b=[Customer Bill] Comp_Data=Value;

  Print Comp_Data;

Run;

TueChristensen
Calcite | Level 5

The example I showed was just part of bigger program and the parts in question is used to generated sets which I iterate over.

Basically what I am doing is defing the set I and J where J(i \in I).

I will look into if I can use the idea of mapping everything into a set of several string (would be something like set<string,string,string, string> in my case) and then use SetOf to create the indices after reading the data.

Thanks for the reply!

TueChristensen
Calcite | Level 5

Got it!

One can use the setof function to extrapolate the data. The drawback is that one has to read all the data into the model, but for my reasonably small problems this will be no problem at all.

The following code does what I want.

data Company_Data;

  input Customer $ Bill $;

  datalines;

  cust1 B1

  cust1 B2

  cust1 B3

  cust2 B4

  cust3 B5

  ;

proc optmodel;

set<string> Customers init {};

set<string> Bills{c in Customers};

set<string, string> AllData;

read data Company_Data into AllData=[customer Bill];

/*This is what I want */

Customers = (setof{<i,j> in AllData} i);

for {c in Customers} Bills = (setof{<i,b> in AllData: i=c} b);

put Customers;

put Bills

  • ;
  • quit;

    RobPratt
    SAS Super FREQ

    Glad you got it working.  Below is an alternative approach that passes through the data only once (instead of once per customer) after reading it.  For large data, you might see a performance improvement.

    proc optmodel;

    set<string> Customers init {};

    set<string> Bills{c in Customers} init {};

    set<string, string> AllData;

    read data Company_Data into AllData=[customer Bill];

    /*This is what I want */

    for {<i,j> in AllData} do;

       Customers = Customers union {i};

       Bills = Bills union {j};

    end;

     

    put Customers;

    put Bills

  • ;
  • quit;

    TueChristensen
    Calcite | Level 5

    Hi RobPratt,

    Your approach surely seem to be more efficient! I will try it out for my final implementation.

    Thanks!

    sas-innovate-2024.png

    Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

    Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

     

    Register now!

    Multiple Linear Regression in SAS

    Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

    Find more tutorials on the SAS Users YouTube channel.

    Discussion stats
    • 5 replies
    • 1158 views
    • 6 likes
    • 3 in conversation