1

I have this data frame showing similar data as BOM and I created a loop to find the accumulative prices of the items from A(raw material), B(sub-assembly) and to C(finished product).

df$final_price = 0

maxLevel <- max(df$productionlevel)

df[df$price != 0, 'final_price'] <- df[df$price != 0, 'quantity'] * df[df$price != 0, 'price']

for (level in (maxLevel - 1):0) {
  condition <- df$productionlevel == level & df$itemtype != "A"
  if (any(condition)) {
    higherLevel <- level + 1
    df[condition, 'final_price'] <- sum(df[df$productionlevel == higherLevel, 'final_price']) * df[condition, 'quantity']
  }
}

I want to use the same logic as this loop but with a recursive function in R (tidyverse). Can anyone help?

If I run dput(df), This is the structure of my dataframe:

structure(list(item_id = c("i1", "i2", "i3", "i4", "i5", "i6", 
"i7", "i8", "i9"), quantity = c(2, 2, 5, 1, 1, 2, 4, 1, 1), price = c(2, 
5, 3, 7, 10, 0, 4, 0, 0), itemtype = c("A", "A", "A", "A", "A", 
"B", "A", "B", "C"), productionlevel = c(3, 3, 3, 3, 2, 2, 1, 
1, 0)), class = "data.frame", row.names = c(NA, -9L))

I want to use the same logic as this loop but with a recursive function in R (tidyverse) to find these accumulative costs. Can anyone help?

user438383
  • 5,716
  • 8
  • 28
  • 43
LHA
  • 39
  • 4
  • Welcome to Stack Overflow LHA! If possible, please use a reproducible example (see link here for details: https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). These help respondents better understand and diagnose your issue. In your case, would you be able to run `dput(df)` on your dataframe and post the output in your question? – Sean McKenzie Feb 21 '23 at 07:27
  • I did run dput(df) and the structure of my data frame is shown in my question now. I know I can face issues with the stack (I already did) when running a recursive function. I want to find an optimized way to use it. If you have any ideas on weither it's better to stick with a loop or use recursion please share. – LHA Feb 21 '23 at 07:42

1 Answers1

2

Here is a pretty straightforward translation of the above for loop into a recursive function approach. Btw. recursive functions have nothing to do with the tidyverse.

adjust_price <- function(df, maxLevel = max(df$productionlevel), level = maxLevel - 1) {
  condition <- df$productionlevel == level & df$itemtype != "A"
  if (any(condition)) {
    higherLevel <- level + 1
    df[condition, 'final_price'] <- sum(df[df$productionlevel == higherLevel, 'final_price']) * df[condition, 'quantity']
  }
  if (level >= 0 ) {
    adjust_price(df, maxLevel = maxLevel, level = level - 1)
  } else {
    return(df)
  }
}

# this part is not part of the recursive function and we do it as preprocessing:
df$final_price = 0
df[df$price != 0, 'final_price'] <- df[df$price != 0, 'quantity'] * df[df$price != 0, 'price']

adjust_price(df)
#>   item_id quantity price itemtype productionlevel final_price
#> 1      i1        2     2        A               3           4
#> 2      i2        2     5        A               3          10
#> 3      i3        5     3        A               3          15
#> 4      i4        1     7        A               3           7
#> 5      i5        1    10        A               2          10
#> 6      i6        2     0        B               2          72
#> 7      i7        4     4        A               1          16
#> 8      i8        1     0        B               1          82
#> 9      i9        1     0        C               0          98

Data from OP

df <- structure(list(item_id = c("i1", "i2", "i3", "i4", "i5", "i6", 
                                 "i7", "i8", "i9"), quantity = c(2, 2, 5, 1, 1, 2, 4, 1, 1), price = c(2, 
                                                                                                       5, 3, 7, 10, 0, 4, 0, 0), itemtype = c("A", "A", "A", "A", "A", 
                                                                                                                                              "B", "A", "B", "C"), productionlevel = c(3, 3, 3, 3, 2, 2, 1, 
                                                                                                                                                                                       1, 0)), class = "data.frame", row.names = c(NA, -9L))

Created on 2023-02-21 by the reprex package (v2.0.1)

TimTeaFan
  • 17,549
  • 4
  • 18
  • 39
  • I updated the df to df2 (please check my answer) Now I want to use the function to group by product_id – LHA Feb 21 '23 at 11:46
  • I updated the df to df2 (please check my answer) Now I want to use the function to group by product_id please check my new question: https://stackoverflow.com/questions/75520415/setting-loop-inside-a-recursive-function – LHA Feb 21 '23 at 12:18