Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Conformability with an empty selection

    Here's my problem: select(1,0) \ 999 gives a conformability error. Apparently, select(1,0) is not conformable with anything except itself, since select(1,0) , 999 errors out but select(1,0)\select(1,0) works, as does the same with a comma. Strangely (to me), select((1\1),(0\0)) \ 999 runs without a hitch.

    Long version: There are three products that might sell out in future days. I've predicted these sellouts in a 0/1 matrix (1=sellout expected, days on rows, products on columns) and want to grab the day of the first predicted sellout for each product. If no sellout is predicted, there's a default "day" of 999:

    Code:
    // two days left works fine:
    days = 51\52
    pred_sellout = (0,0,1) \ (0,0,1)
    
    res = J(1,3,.)
    for (j=1;j<=3;j++) res[j] = (select(days,pred_sellout[,j])\999)[1]
    
    // one day left breaks
    days = 52
    pred_sellout = (0,0,1)
    
    res = J(1,3,.)
    for (j=1;j<=3;j++) res[j] = (select(days,pred_sellout[,j])\999)[1]
    // conformability error for j = 1
    I realize I could write a special rule for treatment of the one-day case:

    Code:
    res[j] = length(days) > 1 ? (select(days,pred_sellout[j])\999)[1] : (pred_sellout[j] ? days : 999)
    However, that's terribly clunky and I'm sure there's a way around this conformability error. How could select(1,0) be conformable with nothing?
    Last edited by Frank Erickson; 15 May 2015, 16:15.

  • #2
    Hi
    This is not an explanation, but a clarification.
    The code select(1,0) returns an empty matrix J(0,0,.) which isn't expandable with either rows or columns.

    Code:
    // select(1,0) returns the empty matrix J(0,0,.) 
    : select(1,0) == J(0,0,.)
      1
    // And you can't expand J(0,0,.) in any direction
    : J(0,0,.) \ 999
                     <istmt>:  3200  conformability error
    r(3200);
    // To expand rowwise the empty matrix must have a column in the empty matrix:
    : J(0,1,.) \ 999
      999
    // To expand columnwise the empty matrix must have a row in the empty matrix:
    : J(1,0,.) , 999
      999
    // And there is no problems expanding : J(0,0,.)  with itself
    : J(0,0,.) , J(0,0,.)
    It has been a puzzle to me why the design is so for J(0,0,.), but there it is
    Kind regards

    nhb

    Comment


    • #3
      hi again
      I think I'll use functions instead, like eg:
      Code:
      // In a column vector of 0/1 use the first index to get a lookup value. If none is found use default value 999
      : function lookup_first(cvec, lookup) return (any(cvec:==1) ? lookup[min(select( (1..rows(cvec))', cvec:==1))] : 999)
      
      : days = 51\52
      : pred_sellout = (0,0,1) \ (0,0,1)
      
      // It works in the first case
      : res = J(1,cols(pred_sellout),.)
      : for (j=1;j<=3;j++) res[j] = lookup_first(pred_sellout[,j], days)
      : res
               1     2     3
          +-------------------+
        1 |  999   999    51  |
          +-------------------+
      
      // And in the second case too
      : days = 52
      : pred_sellout = (0,0,1)
      
      : res = J(1,cols(pred_sellout),.)
      : for (j=1;j<=3;j++) res[j] = lookup_first(pred_sellout[,j], days)
      : res
               1     2     3
          +-------------------+
        1 |  999   999    52  |
          +-------------------+
      Last edited by Niels Henrik Bruun; 18 May 2015, 13:50.
      Kind regards

      nhb

      Comment


      • #4
        Or better still:
        Code:
        function lookup_first(cvec, lookup) 
        {
            value = 999
            if (any(cvec:==1)){
                first_index = min(select( (1..rows(cvec))', cvec:==1))
                value = lookup[first_index]
            }
            return(value)
        }
        
        function loop_through_cols(col_mat, lookup)
        {
            res = J(1,cols(col_mat),.)
            for (j=1;j<=cols(col_mat);j++) {
                res[j] = lookup_first(col_mat[,j], lookup)
            }
            return(res)
        }
        
        loop_through_cols((0,0,1\0,0,1), (51\52))
        loop_through_cols((0,0,1), 52)
        Kind regards

        nhb

        Comment


        • #5
          Ah, thanks Niels! I guess there must be some reason for it, but it sure does make it hard to work with.

          On the plus side, the workaround I had to do made my code more readable, I guess:

          Code:
          soldout_days = select(days,pred_sellout[j])
          firstout     = length(soldout_days) ? soldout_days[1] : 999

          Comment


          • #6
            you're welcome
            And your workaround is indeed quite elegant
            Kind regards

            nhb

            Comment

            Working...
            X