Forum Discussion

tomekm's avatar
tomekm
Icon for Helper III rankHelper III
1 year ago
Solved

Calculate price evolution: which is the difference in yearly prices for a given project value

Hello,

 

I'm trying to calculate a "price evolution" calculation with a calculated column, so that for each project we calculate the difference between the first period (price 1) and its last period (where a value is available). My table looks like the following, and the last column is the expected outcome: 
- For project a, price 1 - price 2, divided by 2 (since there's only 2 year columns containing a 'price' value for this project), and then divided by price 1 column. Please advise. 

 

projectprice1price2price3price4price erosion (percentage)
a25  -0.75
b345 -0.22
c67930.125

 

 

Thank you.

  • Hi tomekm 

     

    Try the following:

    Price erosion = 
    -- Capture the value from the 'price1' column of the table.
    VAR _price1 = tbl[price1]
    
    -- Create a filtered table '_tbl' using SELECTCOLUMNS, assigning indices (1, 2, 3, 4) to prices.
    -- The SELECTCOLUMNS function assigns column names ("Index" and "Price") to the two columns.
    -- Then, the FILTER function removes any rows where 'Price' is blank.
    VAR _tbl =
        FILTER (
            SELECTCOLUMNS (
                {
                    ( 1, tbl[price1] ), -- Assign 1 to 'price1'
                    ( 2, tbl[price2] ), -- Assign 2 to 'price2'
                    ( 3, tbl[price3] ), -- Assign 3 to 'price3'
                    ( 4, tbl[price4] )  -- Assign 4 to 'price4'
                },
                "Index", [Value1],  -- 'Index' column represents the position of each price
                "Price", [Value2]   -- 'Price' column represents the actual price values
            ),
            NOT ( ISBLANK ( [Price] ) )  -- Filter out rows where 'Price' is blank
        )
    
    -- Combine the non-blank prices into a string separated by "|" using CONCATENATEX, 
    -- and sort the prices by 'Index' (ascending order).
    VAR _concat =
        CONCATENATEX ( _tbl, [Price], "|", [Index], ASC )
    
    -- Calculate the length of the concatenated string (number of price values).
    VAR _len =
        PATHLENGTH ( _concat )
    
    -- Extract the latest (last) price from the concatenated string.
    VAR _latestprice =
        PATHITEM ( _concat, _len, 1 )
    
    -- Calculate the difference between the first price (_price1) and the latest price (_latestprice).
    VAR _diff = _price1 - _latestprice
    
    -- Return the price erosion calculation as the difference divided by the length of the prices,
    -- and then divide by the initial price (_price1) to normalize the value.
    RETURN
        DIVIDE ( DIVIDE ( _diff, _len ), _price1 )
    

    Note: Index in the _tbl variable is important as CONCATENATEX combines values by ascending order if no order column is specified.

6 Replies

  • tomekm 

    you can select the first column and unpivot other columns in pq

     

     

    then create a measure

     

    Measure =
    var _last=max('Table'[Attribute])
    var _first=min('Table'[Attribute])
    return (maxx(FILTER('Table','Table'[Attribute]=_first),'Table'[Value])-maxx(FILTER('Table','Table'[Attribute]=_last),'Table'[Value]))/COUNTROWS('Table')/maxx(FILTER('Table','Table'[Attribute]=_first),'Table'[Value])
     
     
    pls see the attachment below
    • tomekm's avatar
      tomekm
      Icon for Helper III rankHelper III

      Thank you, but I really need to be able to accomplish this using DAX only, and not through PQ. Any ideas of how to solve this? Appreciate it. 

      • ryan_mayu's avatar
        ryan_mayu
        Icon for Super User rankSuper User

        tomekm 

        then you can try this

         

        Column =
        var _count=ISBLANK('Table'[price3])+ISBLANK('Table'[price4])
        return SWITCH(TRUE(),_count=0,('Table'[price1]-'Table'[price4])/4/'Table'[price1],_count=1,('Table'[price1]-'Table'[price3])/3/'Table'[price1],('Table'[price1]-'Table'[price2])/2/'Table'[price1])
         
  • Hi,

    Share some sample raw data to work with.  Share data in a format that can be pasted in an MS Excel file.

  • Hi tomekm 

     

    Try the following:

    Price erosion = 
    -- Capture the value from the 'price1' column of the table.
    VAR _price1 = tbl[price1]
    
    -- Create a filtered table '_tbl' using SELECTCOLUMNS, assigning indices (1, 2, 3, 4) to prices.
    -- The SELECTCOLUMNS function assigns column names ("Index" and "Price") to the two columns.
    -- Then, the FILTER function removes any rows where 'Price' is blank.
    VAR _tbl =
        FILTER (
            SELECTCOLUMNS (
                {
                    ( 1, tbl[price1] ), -- Assign 1 to 'price1'
                    ( 2, tbl[price2] ), -- Assign 2 to 'price2'
                    ( 3, tbl[price3] ), -- Assign 3 to 'price3'
                    ( 4, tbl[price4] )  -- Assign 4 to 'price4'
                },
                "Index", [Value1],  -- 'Index' column represents the position of each price
                "Price", [Value2]   -- 'Price' column represents the actual price values
            ),
            NOT ( ISBLANK ( [Price] ) )  -- Filter out rows where 'Price' is blank
        )
    
    -- Combine the non-blank prices into a string separated by "|" using CONCATENATEX, 
    -- and sort the prices by 'Index' (ascending order).
    VAR _concat =
        CONCATENATEX ( _tbl, [Price], "|", [Index], ASC )
    
    -- Calculate the length of the concatenated string (number of price values).
    VAR _len =
        PATHLENGTH ( _concat )
    
    -- Extract the latest (last) price from the concatenated string.
    VAR _latestprice =
        PATHITEM ( _concat, _len, 1 )
    
    -- Calculate the difference between the first price (_price1) and the latest price (_latestprice).
    VAR _diff = _price1 - _latestprice
    
    -- Return the price erosion calculation as the difference divided by the length of the prices,
    -- and then divide by the initial price (_price1) to normalize the value.
    RETURN
        DIVIDE ( DIVIDE ( _diff, _len ), _price1 )
    

    Note: Index in the _tbl variable is important as CONCATENATEX combines values by ascending order if no order column is specified.