panman - 2 months ago 14

R Question

Still new to

`data.table`

I have a

`data.table`

`mydt <- data.table(ID = c("a", "a", "a", "b", "b", "b"),`

col1 = c(1, 2, 3, 4, 5, 6),

col2 = c(7, 8, 9, 10, 11, 12),

key = "ID")

I wrote a function that takes

`mydt`

`data.table`

`data.table`

`myfun <- function(data, constant, column) {`

data <- split(x = data, by = key(data))

data <- lapply(data, function(i) {

i[ , (column) := get(column)*constant]

})

return(data)

}

x <- myfun(data = mydt, constant = 3, column = "col1")

x

$a

ID col1 col2

1: a 3 7

2: a 6 8

3: a 9 9

$b

ID col1 col2

1: b 12 10

2: b 15 11

3: b 18 12

If I understand correctly the scoping rules in R,

`lapply`

`column`

`constant`

`myfun`

However, the function passed to

`lapply`

`data.table`

`split.dt <- function(data) {`

split(data, by = key(data))

}

mult <- function(data) {

lapply(data, function(i) {

i[ , (column) := get(column)*constant]

})

}

myfun <- function(data, constant, column) {

data <- split.dt(data = data)

data <- mult(data = data)

}

x <- myfun(data = mydt, constant = 3, column = "col1")

An error is returned:

`Error in eval(expr, envir, enclos) : object 'column' not found`

What I tried is wrapping

`column`

`i[ , eval(column)]`

`i[ , eval(column)]`

`mult`

`parent.frame()`

`parent.env()`

`sys.call`

`myfun`

`mult`

`split.dt <- function(data) {`

split(data, by = key(data))

}

mult <- function(data) {

supplied.col <- sys.call(which = -1)[["column"]]

supplied.constant <- sys.call(which = -1)[["constant"]]

lapply(data, function(i) {

i[ , eval(supplied.col) := get(supplied.col)*supplied.constant]

})

}

myfun <- function(data, constant, column) {

data <- split.dt(data = data)

data <- mult(data = data)

}

x <- myfun(data = mydt, constant = 3, column = "col1")

x

$a

ID col1 col2

1: a 3 7

2: a 6 8

3: a 9 9

$b

ID col1 col2

1: b 12 10

2: b 15 11

3: b 18 12

It does work, BUT I am not sure if:

- This is the right or most efficient approach. What is the way to make look up at the arguments supplied to
`mult`

?`myfun`

- Will this work if the functions are wrapped in a package?

Answer

**1)** Just pass `column`

and `constant`

to `mult`

as additional arguments.

```
mult <- function(data, constant, column) {
lapply(data, function(i) {
i[ , (column) := get(column)*constant]
})
}
myfun <- function(data, constant, column) {
data <- split.dt(data = data)
data <- mult(data, constant, column)
}
```

**2)** Alternately define `mult`

as:

```
mult <- function(data, envir = parent.frame()) with(envir,
lapply(data, function(i) {
i[ , (column) := get(column)*constant]
})
)
```

**2a)** or

```
mult <- function(data, envir = parent.frame()) {
constant <- envir$constant
column <- envir$column
lapply(data, function(i) {
i[ , (column) := get(column)*constant]
})
}
```