una - poligono en r
Añadir varias columnas a R data.table en una llamada de función? (4)
¿Por qué no hacer que su función tome un marco de datos y devuelva un marco de datos directamente?
myfun <- function (DT)
{
DT$ret1 = with(DT, y + v)
DT$ret2 = with(DT, y - v)
return(DT)
}
Tengo una función que devuelve dos valores en una lista. Ambos valores deben agregarse a una tabla de datos en dos columnas nuevas. La evaluación de la función es costosa, por lo que me gustaría evitar tener que calcular la función dos veces. Aquí está el ejemplo:
library(data.table)
example(data.table)
DT
x y v
1: a 1 42
2: a 3 42
3: a 6 42
4: b 1 4
5: b 3 5
6: b 6 6
7: c 1 7
8: c 3 8
9: c 6 9
Aquí hay un ejemplo de mi función. Recuerde que dije que es un cálculo costoso, además de eso, no hay forma de deducir un valor de retorno de los otros valores dados (como en el ejemplo a continuación):
myfun <- function (y, v)
{
ret1 = y + v
ret2 = y - v
return(list(r1 = ret1, r2 = ret2))
}
Esta es mi manera de agregar dos columnas en una declaración. Sin embargo, uno necesita llamar a myfun dos veces:
DT[,new1:=myfun(y,v)$r1][,new2:=myfun(y,v)$r2]
x y v new1 new2
1: a 1 42 43 -41
2: a 3 42 45 -39
3: a 6 42 48 -36
4: b 1 4 5 -3
5: b 3 5 8 -2
6: b 6 6 12 0
7: c 1 7 8 -6
8: c 3 8 11 -5
9: c 6 9 15 -3
¿Alguna sugerencia sobre cómo hacer esto? Podría guardar r2
en un entorno diferente cada vez que llamo a myfun, solo necesito una forma de agregar dos columnas por referencia a la vez.
La respuesta no se puede usar, como cuando la función no está vectorizada.
Por ejemplo, en la siguiente situación, no funcionará según lo previsto:
myfun <- function (y, v, g)
{
ret1 = y + v + length(g)
ret2 = y - v + length(g)
return(list(r1 = ret1, r2 = ret2))
}
DT
# v y g
# 1: 1 1 1
# 2: 1 3 4,2
# 3: 1 6 9,8,6
DT[,c("new1","new2"):=myfun(y,v,g)]
DT
# v y g new1 new2
# 1: 1 1 1 5 3
# 2: 1 3 4,2 7 5
# 3: 1 6 9,8,6 10 8
Siempre agregará el tamaño de la columna g
, no el tamaño de cada vector en g
Una solución en tal caso es:
DT[, c("new1","new2") := data.table(t(mapply(myfun,y,v,g)))]
DT
# v y g new1 new2
# 1: 1 1 1 3 1
# 2: 1 3 4,2 6 4
# 3: 1 6 9,8,6 10 8
Para construir sobre la respuesta anterior, uno puede usar lapply
con una función que lapply
más de una columna. Entonces es posible usar la función con más columnas de data.table.
myfun <- function(a,b){
res1 <- a+b
res2 <- a-b
list(res1,res2)
}
DT <- data.table(z=1:10,x=seq(3,30,3),t=seq(4,40,4))
DT
## DT
## z x t
## 1: 1 3 4
## 2: 2 6 8
## 3: 3 9 12
## 4: 4 12 16
## 5: 5 15 20
## 6: 6 18 24
## 7: 7 21 28
## 8: 8 24 32
## 9: 9 27 36
## 10: 10 30 40
col <- colnames(DT)
DT[, paste0(c(''r1'',''r2''),rep(col,each=2)):=unlist(lapply(.SD,myfun,z),
recursive=FALSE),.SDcols=col]
## > DT
## z x t r1z r2z r1x r2x r1t r2t
## 1: 1 3 4 2 0 4 2 5 3
## 2: 2 6 8 4 0 8 4 10 6
## 3: 3 9 12 6 0 12 6 15 9
## 4: 4 12 16 8 0 16 8 20 12
## 5: 5 15 20 10 0 20 10 25 15
## 6: 6 18 24 12 0 24 12 30 18
## 7: 7 21 28 14 0 28 14 35 21
## 8: 8 24 32 16 0 32 16 40 24
## 9: 9 27 36 18 0 36 18 45 27
## 10: 10 30 40 20 0 40 20 50 30
Puede almacenar la salida de su llamada de función:
z <- myfun(DT$y,DT$v)
head(DT[,new1:=z$r1][,new2:=z$r2])
# x y v new1 new2
# [1,] a 1 42 43 -41
# [2,] a 3 42 45 -39
# [3,] a 6 42 48 -36
# [4,] b 1 4 5 -3
# [5,] b 3 5 8 -2
# [6,] b 6 6 12 0
pero esto también parece funcionar:
DT[, c("new1","new2") := myfun(y,v), with = FALSE]
Nuevo en data.table
v1.8.3 en R-Forge, with = FALSE
ya no es necesario aquí, por conveniencia:
DT[, c("new1","new2") := myfun(y,v)]
Hasta el minuto en vivo NOTICIAS está here .