data.table에서 : =를 사용하여 여러 열을 그룹별로 지정


130

data.table?를 사용하여 여러 열에 할당하는 가장 좋은 방법은 무엇입니까 ? 예를 들면 다음과 같습니다.

f <- function(x) {c("hi", "hello")}
x <- data.table(id = 1:10)

다음과 같이하고 싶습니다 (물론이 구문이 올바르지 않습니다).

x[ , (col1, col2) := f(), by = "id"]

그리고 그것을 확장하기 위해 변수에 이름이 저장된 많은 열이있을 수 있습니다 (예 col_names:).

x[ , col_names := another_f(), by = "id", with = FALSE]

이와 같은 작업을 수행하는 올바른 방법은 무엇입니까?


1
응답이 마치 것 같습니다 : stackoverflow.com/questions/11308754/…
Alex

Alex, 그 대답은 가깝지만 by@Christoph_J가 올바른 말 과 함께 작동하지 않는 것 같습니다 . FR # 2120에 추가 된 질문에 대한 링크 ": LHS에 == 거짓이 필요합니다.
매트 Dowle

명확히하기 f()위해 각 열마다 하나씩 여러 값을 반환하는 함수입니다.
smci

답변:


161

이것은 R-Forge의 v1.8.3에서 작동합니다. 강조해 주셔서 감사합니다!

x <- data.table(a = 1:3, b = 1:6) 
f <- function(x) {list("hi", "hello")} 
x[ , c("col1", "col2") := f(), by = a][]
#    a b col1  col2
# 1: 1 1   hi hello
# 2: 2 2   hi hello
# 3: 3 3   hi hello
# 4: 1 4   hi hello
# 5: 2 5   hi hello
# 6: 3 6   hi hello

x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][]
#    a b col1  col2 mean sum
# 1: 1 1   hi hello  2.5   5
# 2: 2 2   hi hello  3.5   7
# 3: 3 3   hi hello  4.5   9
# 4: 1 4   hi hello  2.5   5
# 5: 2 5   hi hello  3.5   7
# 6: 3 6   hi hello  4.5   9 

mynames = c("Name1", "Longer%")
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a]
#     a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27


x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][]  # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][]   # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

with인수를 사용하는 이전 버전 (가능한 경우이 인수를 권장하지 않음) :

x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

이 답변과 예제에 감사드립니다. 두 행이있는 하나의 열이 아니라 희미 한 출력에서 ​​각 objectName에 대해 두 개의 열을 얻으려면 다음 줄을 어떻게 수정해야합니까? data.table(objectName=ls())[,c("rows","cols"):=dim(get(objectName)),by=objectName](내가 사용하고 data.table1.8.11)
dnlbrky

@dnlbrky dim는 벡터를 반환하므로 list이를 회전해야 벡터로 변환 할 수 있습니다. 예 [,c("rows","cols"):=as.list(dim(get(objectName))),by=objectNa‌​me]. 문제는 as.list호출 오버 헤드가 있고 작은 벡터를 복사하는 것입니다. 그룹 수가 증가함에 따라 효율성이 문제가되는 경우 알려주십시오.
Matt Dowle

1
안녕 매트. 두 번째 코드 블록 (예 :)의 첫 번째 예는 x[,mynames:=list(mean(b)*4,sum(b)*3),by=a,with=FALSE][]이제 경고를 표시하므로 제거 하시겠습니까? 관련 메모에서와 options(datatable.WhenJisSymbolThenCallingScope=TRUE)같이 과제 x[,mynames:=list(mean(b)*4,sum(b)*3),by=a]가 실제로 작동해야한다고 제안한 사람이 있습니까? 기존 사용자 코드 (?)가 너무 많이 손상 될 수 있지만 다른 변경 사항과 일치하는 것 같습니다.
조쉬 오브라이언

1
@PanFrancisco by=a그것이 없으면 작동하지만 다른 답변을 반환합니다. mean(a)sum(a)집계는 경우 각 그룹 내에서 재생되고 있습니다 by=a. 없이 by=a그냥 막대기 meansum각 셀에 전체 열 (즉, 다른 번호)에 대한합니다.
매트 Dowle

1
@MattDowle 내 함수가 이미 명명 된 목록을 반환하는 경우 어쨌든 다시 이름을 지정하지 않고 dt에 열을 추가 할 수 있습니까? 예를 들어, f <-function (x) {list ( "c"= "hi", "d"= "hello")}는 x [, f (), = a] []으로 명명 된 cols로 결과를 인쇄합니다. 결과를 dt에 추가하는 방법을 모르겠습니다.
Jfly

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.