반응형
data.table의 지정된 모든 열에 동일한 함수를 적용하는 방법
특정 열에서 동일한 작업을 수행하려는 data.table이 있습니다. 이 열의 이름은 문자형 벡터로 제공됩니다. 이 특정 예에서는이 모든 열에 -1을 곱하고 싶습니다.
관련 열을 지정하는 일부 장난감 데이터 및 벡터 :
library(data.table)
dt <- data.table(a = 1:3, b = 1:3, d = 1:3)
cols <- c("a", "b")
지금은 문자 벡터를 반복하면서 이렇게하고 있습니다.
for (col in 1:length(cols)) {
dt[ , eval(parse(text = paste0(cols[col], ":=-1*", cols[col])))]
}
for 루프없이 직접 수행 할 수있는 방법이 있습니까?
이것은 작동하는 것 같습니다.
dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols]
결과는
a b d
1: -1 -1 1
2: -2 -2 2
3: -3 -3 3
여기에 몇 가지 트릭이 있습니다.
- 에 괄호가 있기 때문에
(cols) :=
결과는cols
"cols"라는 새 변수 대신에 지정된 열에 할당됩니다 . .SDcols
호출에 해당 열만보고 있음을 알리고 해당 열과 관련된 ata.SD
의S
ubset 을 사용할 수D
있습니다.lapply(.SD, ...)
.SD
모든 data.frames 및 data.tables와 같이 열 목록 인 에서 작동합니다 .lapply
그래서 끝에서, 목록을 반환j
같은 외모cols := list(...)
.
편집 : @Arun이 언급했듯이 아마도 더 빠른 또 다른 방법이 있습니다.
for (j in cols) set(dt, j = j, value = -dt[[j]])
열 이름도 변경하고 싶을 때 답변을 추가하고 싶습니다. 이것은 종종 경험적 작업의 경우와 같이 여러 열의 로그를 계산하려는 경우 매우 유용합니다.
cols <- c("a", "b")
out_cols = paste("log", cols, sep = ".")
dt[, c(out_cols) := lapply(.SD, function(x){log(x = x, base = exp(1))}), .SDcols = cols]
업데이트 : 다음은 for 루프없이 수행하는 깔끔한 방법입니다.
dt[,(cols):= - dt[,..cols]]
쉬운 코드 가독성을위한 깔끔한 방법입니다. 그러나 성능에 관해서는 아래 microbenchmark 결과에 따라 Frank의 솔루션 뒤에 머물러 있습니다.
mbm = microbenchmark(
base = for (col in 1:length(cols)) {
dt[ , eval(parse(text = paste0(cols[col], ":=-1*", cols[col])))]
},
franks_solution1 = dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols],
franks_solution2 = for (j in cols) set(dt, j = j, value = -dt[[j]]),
hannes_solution = dt[, c(out_cols) := lapply(.SD, function(x){log(x = x, base = exp(1))}), .SDcols = cols],
orhans_solution = for (j in cols) dt[,(j):= -1 * dt[, ..j]],
orhans_solution2 = dt[,(cols):= - dt[,..cols]],
times=1000
)
mbm
Unit: microseconds
expr min lq mean median uq max neval
base_solution 3874.048 4184.4070 5205.8782 4452.5090 5127.586 69641.789 1000
franks_solution1 313.846 349.1285 448.4770 379.8970 447.384 5654.149 1000
franks_solution2 1500.306 1667.6910 2041.6134 1774.3580 1961.229 9723.070 1000
hannes_solution 326.154 405.5385 561.8263 495.1795 576.000 12432.400 1000
orhans_solution 3747.690 4008.8175 5029.8333 4299.4840 4933.739 35025.202 1000
orhans_solution2 752.000 831.5900 1061.6974 897.6405 1026.872 9913.018 1000
아래 차트와 같이
내 이전 답변 : 다음도 작동합니다.
for (j in cols)
dt[,(j):= -1 * dt[, ..j]]
위의 솔루션 중 어느 것도 그룹 별 계산과 함께 작동하지 않는 것 같습니다. 다음은 내가 얻은 최고입니다.
for(col in cols)
{
DT[, (col) := scale(.SD[[col]], center = TRUE, scale = TRUE), g]
}
library(data.table)
(dt <- data.table(a = 1:3, b = 1:3, d = 1:3))
Hence:
a b d
1: 1 1 1
2: 2 2 2
3: 3 3 3
Whereas (dt*(-1)) yields:
a b d
1: -1 -1 -1
2: -2 -2 -2
3: -3 -3 -3
열의 string 형 벡터를 기반으로 새 열을 만드는 예제를 추가합니다. Jfly 답변을 기반으로 :
dt <- data.table(a = rnorm(1:100), b = rnorm(1:100), c = rnorm(1:100), g = c(rep(1:10, 10)))
col0 <- c("a", "b", "c")
col1 <- paste0("max.", col0)
for(i in seq_along(col0)) {
dt[, (col1[i]) := max(get(col0[i])), g]
}
dt[,.N, c("g", col1)]
반응형
'programing tip' 카테고리의 다른 글
루비 1.9.3의 루비 디버그? (0) | 2020.11.01 |
---|---|
System.Web.Mvc.HtmlHelper가 표시되지 않는 Razor보기 (0) | 2020.11.01 |
LINQ에서 Include ()는 무엇을합니까? (0) | 2020.11.01 |
Redux 상태 및 URL 해시 태그 매개 변수를 동기화하는 방법 (0) | 2020.11.01 |
서식있는 텍스트 형식없이 코드를 복사하여 붙여 넣는 방법 (0) | 2020.11.01 |