Programing

변수 이름이 문자형 벡터에 저장 될 때 data.table 선택 / 할당

crosscheck 2020. 10. 17. 09:13
반응형

변수 이름이 문자형 벡터에 저장 될 때 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)]작동하지 않습니다 (내가 기대하지도 않았습니다).


프로그래밍 방식으로 변수를 선택하는 두 가지 방법 :

  1. with = FALSE:

    DT = data.table(col1 = 1:3)
    colname = "col1"
    DT[, colname, with = FALSE] 
    #    col1
    # 1:    1
    # 2:    2
    # 3:    3
    
  2. '점점'( ..) 접두사 :

    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 = FALSEwith :=의 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 문을 생성 유사를 :evalpaste

expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
# [1] "DT[,col1:=cumsum(col1)]"

eval(parse(text=expr))
#    col1
# 1:    4
# 2:   13
# 3:   28

If you do that a lot, you can define a helper function EVAL :

EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))

EVAL("DT[,",colname,":=cumsum(",colname,")]")
#    col1
# 1:    4
# 2:   17
# 3:   45

Now that data.table 1.8.2 automatically optimizes j for efficiency, it may be preferable to use the eval method. The get() in j prevents some optimizations, for example.

Or, there is set(). A low overhead, functional form of :=, which would be fine here. See ?set.

set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
#    col1
# 1:    4
# 2:   21
# 3:   66

*This is not an answer really, but I don't have enough street cred to post comments :/

Anyway, for anyone who might be looking to actually create a new column in a data table with a name stored in a variable, I've got the following to work. I have no clue as to it's performance. Any suggestions for improvement? Is it safe to assume a nameless new column will always be given the name 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))

Notice I can reference it just fine in the sum() but can't seem to get it to assign in the same step. BTW, the reason I need to do this is colname will be based on user input in a Shiny app.


For multiple columns and a function applied on column values.

When updating the values from a function, the RHS must be a list object, so using a loop on .SD with lapply will do the trick.

The example below converts integer columns to numeric columns

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" 

참고URL : https://stackoverflow.com/questions/12391950/select-assign-to-data-table-when-variable-names-are-stored-in-a-character-vect

반응형