0

I have hundreds of formulas stored in a vector, and need apply those formulas to tree variables (called dbh and ht) in a dataframe. The situation can be reproduced as follows:

vec_formulas = c('0.32*dbh^1.22*ht^0.99',
                 '0.44 + 3.55*log(dbh) + log(ht)^1.03',
                 '0.40*dbh^1.30 + ht*1.12')  # wrote only 3, but there are many

set.seed(123)
df_trees = data.frame(tree = 1:200,
                dbh = rnorm(200, mean=30),
                ht = rnorm(200, mean=15))

I need some result that apply every formula to every tree. If necessary, I can transform 'vec_formulas' into dataframe or datatable.

Thanks in advance!

-H.

  • 2
    Does this answer your question? [Evaluate expression given as a string](https://stackoverflow.com/questions/1743698/evaluate-expression-given-as-a-string) – Ian Campbell May 04 '22 at 03:51

2 Answers2

0

I think this does what you want although it does not use dplyr. I'm just applying it to the first 10 rows of df_trees. Just change "df_trees[1:10, ]" to "df_trees" to run it on all 200:

results <- matrix(nrow=nrow(df_trees[1:10, ]), ncol=length(vec_formulas))
for (i in seq(vec_formulas)) {
    for (j in seq(nrow(df_trees[1:10, ]))) {
        dbh <- df_trees[j, 2]
        ht <- df_trees[j, 3]
        results[j, i] <- eval(str2expression(vec_formulas[i]))
    }
}
results
#           [,1]     [,2]     [,3]
#  [1,] 331.4278 15.38278 51.74671
#  [2,] 318.8233 15.36617 51.22853
#  [3,] 309.5550 15.46535 52.05921
#  [4,] 307.6852 15.35055 50.80042
#  [5,] 289.6031 15.29000 49.81286
#  [6,] 307.0097 15.46758 52.05195
#  [7,] 286.0400 15.30129 49.87349
#  [8,] 269.9915 15.10859 47.61103
#  [9,] 319.2932 15.33311 50.95189
# [10,] 289.7923 15.24750 49.38832
dcarlson
  • 10,936
  • 2
  • 15
  • 18
0

Using data.table:

library(data.table)
expr   <- str2expression(vec_formulas)
result <- setDT(df_trees)[, lapply(expr, \(x) eval(x)), by=.(tree, dbh, ht)]
head(result)
##    tree      dbh       ht       V1       V2       V3
## 1:    1 29.43952 17.19881 331.4278 15.38278 51.74671
## 2:    2 29.76982 16.31241 318.8233 15.36617 51.22853
## 3:    3 31.55871 14.73485 309.5550 15.46535 52.05921
## 4:    4 30.07051 15.54319 307.6852 15.35055 50.80042
## 5:    5 30.12929 14.58566 289.6031 15.29000 49.81286
## 6:    6 31.71506 14.52375 307.0097 15.46758 52.05195

Note: If you're using R < 4.1 you'll need

result <- setDT(df_trees)[, lapply(expr, function(x) eval(x)), by=.(tree, dbh, ht)]

The function shorthand \(x), which is equivalent to function(x) was introduced in 4.1.

jlhoward
  • 58,004
  • 7
  • 97
  • 140