2013-10-17 3 views
2

금융 센터에서 메시지를 삭제하는 재정적 문제로 작업 중입니다. data.table을 사용하고 있으며 성능과 취급이 매우 만족 스럽습니다.여러 변수의 행을 효율적으로 일치 - 열 제외

비록 나는 항상 data.table의 모든 힘을 향상시키고 사용하는 방법을 스스로에게 묻는다.

  1. 내 작업을 수행하기 위해이 효율적인 방법인가, 아니면 않는 존재 뭔가 더 'data.table'

    set.seed(1) 
    DT <- data.table(SYM = c(rep("A", 10), rep("B", 12)), PRC = format(rlnorm(22, 2), digits = 2), VOL = rpois(22, 312), ID = c(seq(1000, 1009), seq(1004, 1015)), FLAG = c(rep("", 8), "R", "A", rep("", 4), "R", rep("", 7))) 
    DT$PRC[9] <- DT$PRC[6] 
    DT$PRC[7] <- DT$PRC[6] 
    DT$VOL[9] <- DT$VOL[6] 
    DT$VOL[7] <- DT$VOL[6] 
    DT$PRC[15] <- DT$PRC[13] 
    DT$VOL[15] <- DT$VOL[13] 
    ## See the original dataset 
    DT 
    ## Set the key 
    setkey(DT, "SYM", "PRC", "VOL", "FLAG") 
    ## Get all rows, that match a row with FLAG == "R" on the given variables in the list 
    DT[DT[FLAG == "R"][,list(SYM, PRC, VOL)]] 
    ## Remove these rows from the dataset 
    DT <- DT[!DT[FLAG == "R"][,list(SYM, PRC, VOL)]] 
    ## See the modified data.table 
    DT 
    

    내 질문은 지금 : 여기

    내 작업의 예입니다 스타일? 키가 효율적으로 설정 되었습니까?
  2. 일치시킬 변수가 3 개 (SYM, PRC, VOL) ​​일뿐만 아니라 배제와 같은 것이 있으면 작업을 수행하려면 어떻게해야합니까? (데이터를 사용할 수 있음을 알고 있습니다. 프레임 스타일이지만 data.table에 대한보다 우아한 방법이 있는지 알고 싶습니까?
  3. 마지막 명령의 복사 란 무엇입니까? remove row by reference의 스레드 다음에 복사하는 것이 유일한 방법이라고 생각합니다. 여러 가지 작업을 수행하는 경우 어떤 방식으로 복합 작업을 수행하고 각 작업을 복사하지 않아도됩니까?
+0

하나는 데이터 임의 단순히 원하는 것을하지? 나는'rlnorm'을 본다. (나는 그것이 무엇인지는 모르지만). 상단에'set.seed (1)'(또는 다른 시드)를 써서 같은 페이지에 올 수 있습니까?당신은 꽤 많은 일을하고 있습니다 만, DT1 <- DT [! ...] 테이블의 두 가지 버전을 유지할 것입니다. 왜냐하면 메모리 제약 조건에 익숙하지 않기 때문입니다. – Frank

+0

@Frank이 댓글 주셔서 감사합니다! 당신은 사실입니다! 그리고 내 데이터는 전혀 임의가 아닙니다 :) –

답변

1

이 작업을 수행하기 위해 키를 설정하는 경우 @ eddi의 대답이 가장 읽기 쉽고 가장 쉽습니다.

setkey(DT, SYM, PRC, VOL) 
#^as in @eddi's answer, since you are not using the rest of the key 
microbenchmark(
    notjoin=DT[!DT[FLAG == "R"][,list(SYM, PRC, VOL)]], 
    logi_not=DT[!DT[,rep(any(FLAG=='R'),.N),by='SYM,PRC,VOL']$V1], 
    idx_not=DT[!DT[,if(any(FLAG=='R')){.I}else{NULL},by='SYM,PRC,VOL']$V1], 
    SD=DT[,if(!any(FLAG=='R')){.SD}else{NULL},by='SYM,PRC,VOL'], 
    eddi=DT[!DT[FLAG == "R"]], 
    times=1000L 
) 

결과 : 한편

Unit: milliseconds 
    expr  min  lq median  uq  max neval 
    notjoin 4.983404 5.577309 5.715527 5.903417 66.468771 1000 
logi_not 4.393278 4.960187 5.097595 5.273607 66.429358 1000 
    idx_not 4.523397 5.139439 5.287645 5.453129 15.068991 1000 
     SD 3.670874 4.180012 4.308781 4.463737 9.429053 1000 
    eddi 2.767599 3.047273 3.137979 3.255680 11.970966 1000 

옵션 중 일부는 위의 작업이 키에 의해 그룹화하는 것을 포함 할 것을 요구하지 않는다.

  • 은 (는 변경하지 않는) 또는
  • 이 사본을하기 전에이 사용하는 다른 그룹과 같은 여러 작업을 수행 할 키 이외 한번 사용하여 그룹을하고 있습니다 ... 중 하나를 가정 행을 삭제하는 조작 newDT <- DT[...] (OP의 포인트 3에서 언급 한대로).

.

setkey(DT,NULL) 
shuffDT <- DT[sample(1:nrow(DT))] # not realistic, of course 
# same benchmark with shuffDT, but without methods that require a key 
# Unit: milliseconds 
#  expr  min  lq median  uq  max neval 
# logi_not 4.466166 5.120273 5.298174 5.562732 64.30966 1000 
# idx_not 4.623821 5.319501 5.517378 5.799484 15.57165 1000 
#  SD 4.053672 4.448080 4.612213 4.849505 66.76140 1000 

이 경우 OP와 eddi의 방법은 사용할 수 없습니다 (가입하려면 키가 필요하기 때문에). 일회성 조작의 경우 .SD을 사용하는 것이 더 빠를 것 같습니다. 여러 기준에 의한 하위 집합을 만들려면 복사하기 전에 유지/삭제하려는 행을 추적하고 싶을 것입니다. newDT <- DT[!union(badrows1,badrows2,...)].

DT[,rn:=1:.N] # same as .I 
badflagrows <- DT[,if(any(FLAG=='R')){rn}else{NULL},by='SYM,PRC,VOL']$V1 
# fill in next_cond, next_grp 
badnextrows <- DT[!badflagrows][, 
    if(any(next_cond)){rn}else{NULL},by='next_grp']$V1 

아마도 비슷한는 조금 빠른 논리적 서브 세트 (벤치 마크에서 "logi_not"), 수행 할 수 있습니다.

1

FLAG에 키를 설정하는 이유는 혼란 스러워요, 당신은

setkey(DT, SYM, PRC, VOL) 

DT[!DT[FLAG == "R"]] 
+0

그래, 훨씬 빠릅니다. – Frank

+0

@eddi 사실, 그렇습니다. 잘 알다시피, 나는이 변수에서 "R"을 검색 할 수 있도록 테이블에 "FLAG"가 있어야한다는 것을 알았습니다. 당신의 도움을 주셔서 대단히 감사합니다! –

관련 문제