2014-11-27 2 views
0

누락 된 데이터를 확인할 수 있도록 특정 data.table을 만들고 싶습니다. 이 경우 누락 된 데이터는 NA가 있다는 것을 의미하지는 않지만 전체 행은 제외됩니다. 그래서 다른 컬럼에서 어떤 레벨의 값이 누락되었는지를 알 수 있어야합니다. 누락 된 값이 많거나 데이터 세트 전체에 퍼져있는 경우에도 중요합니다.이러한 데이터를 효율적으로 병합하는 방법

그래서이 테이블은 6.000.000x5 data.table (테이블 A라고 함)에 시간 종속 변수, 레벨 ID 및 최종 테이블에 추가하려는 값 N이 들어 있습니다.

다른 테이블 (TableB)은 207x2입니다. 이것은 인자에 대한 ID를 TableC의 열에 연결합니다.

표 C는 1.500.000x207이며, 207 개의 각 열은 표 B에 따른 ID에 해당하며 행은 표 A의 시간 종속 변수에 해당합니다.

이 테이블은 크며 ​​최근에 여분의 RAM (총 8GB까지)을 얻었지만 컴퓨터는 TableC를 스왑하고 각 쓰기에 대해 다시 호출해야하며 이후에 다시 스왑됩니다. 이 교환은 내 시간을 소비하는 것입니다. TableA의 행당 약 1.6 초, TableA에 6.000.000 행이 있으므로이 작업은 100 일 이상 논스톱으로 실행됩니다.

현재 for 루프를 사용하여 TableA 행을 반복합니다. 이 for 루프 루프를 아무런 조작없이 거의 즉시 수행합니다. TableA와 TableB에서 TableC에 대한 올바른 열과 행 번호를 찾고 TableA에서 TableC로 값을 쓰는 한 줄 명령을 만들었습니다. 시스템을 수행하기 위해이 한 줄을 끊었습니다. 시간 분석 및 각 단계는 큰 TableC에 쓰는 것을 제외하고는 약 0 초가 걸립니다. 이것은 테이블에 값을 쓰는 것이 가장 시간이 많이 걸리고 내 메모리 사용을보고 있음을 보여주었습니다. 필자는 쓰기가 발생할 때마다 나타나는 거대한 덩어리를 볼 수 있으며, 마자 마자 마자 사라집니다.

TableA <- data.table("Id"=round(runif(200, 1, 100)), "TimeCounter"=round(runif(200, 1, 50)), "N"=round(rnorm(200, 1, 0.5))) 
TableB <- data.table("Id"=c(1:100),"realID"=c(100:1)) 
TSM <- matrix(0,ncol=nrow(TableB), nrow=50) 
TableC <- as.data.table(TSM) 
rm(TSM) 
for (row in 1:nrow(TableA)) 
{ 
    TableCcol <- TableB[realID==TableA[row,Id],Id] 
    TableCrow <- (TableA[row,TimeCounter]) 
    val <- TableA[row,N] 
    TableC[TableCrow,TableCcol] <- val 
} 

에 대한 루프의 마지막 단계에서 메모리 스왑을 방지하여,이 작업을 빠르게하는 방법을 다른 사람이 나에게 조언을 할 수 있습니까?


편집 : @Arun의 조언에 따라 테스트 할 더미 데이터를 개발할 시간이있었습니다. 위에 주어진 코드에 포함되었습니다. 더미 데이터가 무작위이고 루틴이 작동하기 때문에 원하는 결과가 포함되지 않았습니다. 그것은 문제의 속도입니다.

+0

문제의 최소한의 재현 가능한 예와 필요한 솔루션을 제공해주십시오. ATM을 따라 가기에는 텍스트가 너무 많습니다. – Arun

+0

일부 코드는 제공 할 수 있지만 데이터는 제공 할 수 없습니다. 또한 어떻게 메모리 문제의 재현 가능한 예를 만들 수 있습니까? – Gullydwarf

+1

생각해 봅시다. 테이블의 작은 데이터 세트를 생성하는 코드를 제공 할 수 있습니다. 그런 다음 코드가 무엇인지 보여주십시오. 그런 다음 해당 코드의 결과를 보여주십시오. 그런 다음 이것이 데이터 차원에 맞게 확장되지 않는다고 설명하십시오. 그런 다음 메모리 문제를 해결할 수있는 방법을 묻습니다. 또한 메모리 문제를 말하고 "이 작업을 더 빨리 수행하려면 어떻게해야합니까?"라는 질문으로 게시물을 끝내십시오. – Arun

답변

0

내 문제를 다시 생각해 보니 나는 훨씬 빨리 작동하는 해결책을 찾았습니다. 문제는 위에서 제기 한 질문에서 따르지 않는다는 것입니다. 이미 제 질문에 설명 된 상황에 도달하기 위해 몇 가지 조치를 취했기 때문입니다.

내가 TableA를 집계 한 TableX를 입력하십시오. TableX에는 Id 's와 TimeCounters가 포함되어 있으므로 필요한 정보 만 담은 작은 테이블을 만드는 것이 가장 좋습니다. TableX에는 관련 시간이 포함되어 있지만 제 질문에는 시간의 시작부터 완전한 시계열을 사용하고 있습니다 (01-01-1970;)). 내 TableC를 만들기 위해 내 TimeCounter 열의 레벨을 사용하는 것이 훨씬 현명했습니다.

또한 데이터를 병합하는 것이 훨씬 빠르고 데이터를 개별적으로 값을 설정해야했습니다. 그래서 내 충고는 : 값을 많이 설정해야 할 때마다 개별적으로 복사하는 대신 병합 방법을 찾아보십시오.

솔루션 :

# Create a table with time on the row dimension by just using the TimeCounters we find in our original data. 
TableC <- data.table(TimeCounter=as.numeric(levels(factor(TableX[,TimeCounter])))) 
setkey(TableC,TimeCounter) # important to set the correct key for merge. 

# Loop over all unique Id's (maybe this can be reworked into something *apply()ish) 
for (i in levels(factor(TableX[,Id]))) 
{ 
    # Count how much samples we have for Id and TimeCounter 
    TableD <- TableX[Id==i,.N,by=TimeCounter] 
    setkey(TableD,TimeCounter) # set key for merge 
    # Merge with Id on the column dimension 
    TableC[TableD,paste("somechars",i,sep=""):=N] 
} 

내가 TableC 격차를 확인하고 모든 아이디의 누락 된 행을 삽입해야하므로 지금 TimeCounter에서 누락 단계가있을 수 있습니다. 그런 다음 마침내 내 데이터 갭이 어느 정도 얼마나 큰지 확인할 수 있습니다.

0

dplyr/tidyr 패키지를 사용하여 결과를 얻지는 못했지만, for 루프보다 메모리 효율이 좋은 것처럼 보입니다.

install.packages("dplyr") 
install.packages("tidyr") 
library(dplyr) 
library(tidyr) 

TableC <- TableC %>% gather(tableC_id, value, 1:207) 

은 'tableC_id'와 'tableC_value'열 긴 형식 310,500,000x2 테이블에 1,500,000x207에서 TableC를 켭니다.
TableD <- TableA %>% 
    left_join(TableB, c("LevelID" = "TableB_ID")) %>% 
    left_join(TableC, c("TableB_value" = "TableC_id") 

내가 늦게 사용하고 패키지의 몇 가지이며, 그들은 매우 효율적으로 보이지만,이 유용한 기능이 될 수 있도록 data.table 패키지는 큰 테이블의 관리를 위해 특별히 사용됩니다 . 또한 SQL 명령을 통해 data.frames를 쿼리 할 수있는 sqldf를 살펴 보겠습니다.

+0

조언 해 주셔서 감사합니다. 패키지를 살펴 보겠습니다. – Gullydwarf

관련 문제