하나의 함수 호출로 R data.table에 여러 열을 추가 하시겠습니까?
목록에 두 개의 값을 반환하는 함수가 있습니다. 두 값 모두 두 개의 새 열에서 data.table에 추가해야합니다. 함수의 평가는 비용이 많이 들기 때문에 함수를 두 번 계산하는 것을 피하고 싶습니다. 예는 다음과 가변적입니다.
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
여기 내 기능의 예가 있습니다. 비용이 많이 많이 든다고 말한 것을 기억하십시오. 그 외에도 주어진 다른 값에서 하나의 반환 값을 추론 할 방법이 없습니다 (아래 예 참조).
myfun <- function (y, v)
{
ret1 = y + v
ret2 = y - v
return(list(r1 = ret1, r2 = ret2))
}
하나의 문에 두 개의 열을 추가하는 방법은 다음과 같습니다. 그러나 myfun을 두 번 호출해야합니다.
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
이를 수행하는 방법에 대한 제안 제안 사항이 있습니까? r2
myfun을 호출 할 때마다 별도의 환경에 사용할 수 있습니다. 한 번에 참조로 두 개의 열을 추가하는 방법 만 있으면됩니다.
data.table
v1.8.3 부터 다음과 같이 할 수 있습니다.
DT[, c("new1","new2") := myfun(y,v)]
또 다른 옵션은 함수의 출력을 저장하고 열을 하나씩 추가하는 것입니다.
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
이전 답변을 lapply
바탕으로 두 개 이상의 열을 출력하는 함수와 함께 사용할 수 있습니다 . 그러면 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
함수가 벡터화되지 않은 경우와 같이 사용할 수 없습니다.
예를 들어 다음 상황에서는 한대로 작동하지 않습니다.
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
항상 각 g
벡터의 크기가 아닌 열의 크기를 추가합니다 .g
경우 해결책은 다음과 가변적입니다.
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
함수가 많은 것을 반환하는 경우에 거의 모든 목록으로 변환하여 함수를 래핑하여 동일한 동작을 수행 할 수 있습니다. data.table이 자동으로 처리해야 할 사항이 궁금합니다.
matrix2list <- function(mat){
unlist(apply(mat,2,function(x) list(x)),FALSE)
}
DT <- data.table(A=1:10)
myfun <- function(x) matrix2list(cbind(x+1,x-1))
DT[,c("c","d"):=myfun(A)]
##>DT
## A c d
## 1: 1 2 0
## 2: 2 3 1
## 3: 3 4 2
## 4: 4 5 3
## 5: 5 6 4
## 6: 6 7 5
## 7: 7 8 6
## 8: 8 9 7
## 9: 9 10 8
## 10: 10 11 9
함수가 데이터 프레임을 받아 데이터 프레임을 직접 반환하지 않는 이유는 무엇입니까?
myfun <- function (DT)
{
DT$ret1 = with(DT, y + v)
DT$ret2 = with(DT, y - v)
return(DT)
}
'ProgramingTip' 카테고리의 다른 글
배포를 처리하기 위해 pip, virtualenv 및 Fabric을 어떻게 사용합니까? (0) | 2020.11.15 |
---|---|
Django에서 'max_length'의 최대 크기는 얼마입니까? (0) | 2020.11.15 |
컴파일러가 힙 메모리 할당을 최적화 할 수 있습니까? (0) | 2020.11.15 |
Gradle 로그는 어디에 있습니까? (0) | 2020.11.15 |
Elisp에서 기호를 공유로 변환 (0) | 2020.11.15 |