[r] 변수 이름이 문자형 벡터에 저장 될 때 data.table 선택 / 할당
data.table
변수 이름이 문자형 벡터에 저장된 경우에서 변수 를 어떻게 참조 합니까? 예를 들어, 이것은 다음에서 작동합니다 data.frame
.
df <- data.frame(col1 = 1:3)
colname <- "col1"
df[colname] <- 4:6
df
# col1
# 1 4
# 2 5
# 3 6
:=
표기법을 사용하거나 사용하지 않고 data.table에 대해 동일한 작업을 어떻게 수행 할 수 있습니까? 의 명백한 것은 dt[ , list(colname)]
작동하지 않습니다 (또는 기대하지 않았습니다).
답변
프로그래밍 방식으로 변수를 선택하는 두 가지 방법 :
-
with = FALSE
:DT = data.table(col1 = 1:3) colname = "col1" DT[, colname, with = FALSE] # col1 # 1: 1 # 2: 2 # 3: 3
-
‘점점'(
..
) 접두사 :DT[, ..colname] # col1 # 1: 1 # 2: 2 # 3: 3
‘점점'( ..
) 표기법에 대한 자세한 설명은 1.10.2의 새로운 기능 (현재 도움말 텍스트에 설명되어 있지 않음)을 참조하십시오.
변수에 할당 하려면 LHS를 :=
괄호로 묶습니다.
DT[, (colname) := 4:6]
# col1
# 1: 4
# 2: 5
# 3: 6
후자는 전체 열 벡터를 참조로 대체하기 때문에 열 plonk 라고합니다. 하위 집합 i
이 있으면 참조로 하위 할당됩니다. 괄호 (colname)
는 2014 년 10 월 CRAN 버전 v1.9.4에 도입 된 속기입니다. 다음은 뉴스 항목입니다 .
with = FALSE
with:=
의 LHS:=
를 괄호로 감싸는 것이 한동안 선호되었으므로 with 사용 은 이제 모든 경우에 사용되지 않습니다 .
colVar = "col1" DT[, colVar := 1, with = FALSE] # deprecated, still works silently DT[, (colVar) := 1] # please change to this DT[, c("col1", "col2") := 1] # no change DT[, 2:4 := 1] # no change DT[, c("col1","col2") := list(sum(a), mean(b)] # no change DT[, `:=`(...), by = ...] # no change
의 세부 정보 섹션을 참조하십시오 ?`:=`
.
DT[i, (colnamevector) := value]
# [...] The parens are enough to stop the LHS being a symbol
그리고 코멘트에서 추가 질문에 답하기 위해 한 가지 방법이 있습니다 (평소와 같이 여러 가지 방법이 있습니다) :
DT[, colname := cumsum(get(colname)), with = FALSE]
# col1
# 1: 4
# 2: 9
# 3: 15
또는, 당신은 쉽게 읽을 단지에 대한 쓰기 및 디버그 찾을 수 서버에 전송하는 동적 SQL 문을 생성 유사를 :eval
paste
expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
# [1] "DT[,col1:=cumsum(col1)]"
eval(parse(text=expr))
# col1
# 1: 4
# 2: 13
# 3: 28
그렇게 많이하면 도우미 함수를 정의 할 수 있습니다 EVAL
.
EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))
EVAL("DT[,",colname,":=cumsum(",colname,")]")
# col1
# 1: 4
# 2: 17
# 3: 45
이제 data.table
1.8.2가 자동으로 j
효율성을 최적화하므로이 eval
방법 을 사용하는 것이 좋습니다 . get()
에는 j
예를 들어, 어떤 최적화를 방지 할 수 있습니다.
또는 set()
. 오버 헤드가 적고 기능적인 형식 인 :=
. 여기에서는 괜찮습니다. 을 참조하십시오 ?set
.
set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
# col1
# 1: 4
# 2: 21
# 3: 66
답변
* 이것은 실제로 대답은 아니지만 댓글을 게시 할 거리의 신용이 충분하지 않습니다.
어쨌든, 변수에 저장된 이름으로 데이터 테이블에 새 열을 실제로 만들려는 사람을 위해 다음 작업을 수행해야합니다. 성능에 대한 단서가 없습니다. 개선을위한 제안 사항이 있습니까? 이름없는 새 열에 항상 V1이라는 이름이 부여된다고 가정하는 것이 안전합니까?
colname <- as.name("users")
# Google Analytics query is run with chosen metric and resulting data is assigned to DT
DT2 <- DT[, sum(eval(colname, .SD)), by = country]
setnames(DT2, "V1", as.character(colname))
sum ()에서 잘 참조 할 수 있지만 동일한 단계에서 할당 할 수없는 것 같습니다. BTW,이 작업을 수행해야하는 이유는 colname이 Shiny 앱의 사용자 입력을 기반으로하기 때문입니다.
답변
여러 열 및 열 값에 적용된 함수의 경우.
함수에서 값을 업데이트 할 때 RHS는 목록 객체 여야하므로 .SD
with 루프를 사용 lapply
하면 트릭을 수행 할 수 있습니다.
아래 예는 정수 열을 숫자 열로 변환합니다.
a1 <- data.table(a=1:5, b=6:10, c1=letters[1:5])
sapply(a1, class) # show classes of columns
# a b c1
# "integer" "integer" "character"
# column name character vector
nm <- c("a", "b")
# Convert columns a and b to numeric type
a1[, j = (nm) := lapply(.SD, as.numeric ), .SDcols = nm ]
sapply(a1, class)
# a b c1
# "numeric" "numeric" "character"
답변
변수 또는 함수를 통해 data.table에서 여러 열을 검색합니다.
library(data.table)
x <- data.table(this=1:2,that=1:2,whatever=1:2)
# === explicit call
x[, .(that, whatever)]
x[, c('that', 'whatever')]
# === indirect via variable
# ... direct assignment
mycols <- c('that','whatever')
# ... same as result of a function call
mycols <- grep('a', colnames(x), value=TRUE)
x[, ..mycols]
x[, .SD, .SDcols=mycols]
# === direct 1-liner usage
x[, .SD, .SDcols=c('that','whatever')]
x[, .SD, .SDcols=grep('a', colnames(x), value=TRUE)]
모든 양보
that whatever
1: 1 1
2: 2 2
나는 .SDcols
가장 우아한 방법을 찾습니다 .
답변
당신은 이것을 시도 할 수 있습니다
colname <-as.name ( “COL_NAME”)
DT2 <-DT [, list (COL_SUM = sum (eval (colname, .SD))), 기준 = c (그룹)]