2012-01-01 3 views
4

아래 코드는 원하는 출력을 생성합니다. 그러나 벡터 라이 제이션의 부족은 매우 천천히 실행된다는 것을 의미합니다. 어떻게 속도를 높일 수 있습니까?중첩 된 루프로 코드 벡터화/속도 향상

dput 결과를 일부 표시 데이터의 일부로 입력했습니다.

입력 dput S

  1. StandRef 입력

    structure(list(id = structure(c(43L, 50L, 17L, 45L, 9L, 5L, 49L, 
    33L, 48L, 39L, 71L, 64L, 44L, 47L, 58L, 24L, 15L, 37L, 14L, 11L, 
    26L, 57L, 4L, 30L, 72L, 21L, 23L, 60L, 38L, 59L, 29L, 19L, 6L, 
    46L, 36L, 3L, 63L, 55L, 51L, 35L, 10L, 7L, 16L, 73L, 42L, 52L, 
    41L, 27L, 25L, 61L, 20L, 70L, 53L, 18L, 31L, 22L, 1L, 8L, 2L, 
    40L, 65L, 67L, 28L, 56L, 13L, 32L, 54L, 66L, 68L, 34L, 12L, 69L, 
    62L), .Label = c("ID 1009445", "ID 120763", "ID 133883", "ID 136398", 
    "ID 171850", "ID 192595", "ID 197597", "ID 216406", "ID 21888", 
    "ID 230940", "ID 23777", "ID 282791", "ID 306348", "ID 309745", 
    "ID 326928", "ID 344897", "ID 34974", "ID 350157", "ID 391831", 
    "ID 402479", "ID 43010", "ID 484078", "ID 484697", "ID 537134", 
    "ID 562259", "ID 562455", "ID 567042", "ID 572866", "ID 578945", 
    "ID 595683", "ID 59759", "ID 598460", "ID 603611", "ID 603757", 
    "ID 607991", "ID 60976", "ID 622720", "ID 646989", "ID 656144", 
    "ID 668807", "ID 669435", "ID 720522", "ID 740555", "ID 745499", 
    "ID 746001", "ID 783969", "ID 78979", "ID 792426", "ID 793541", 
    "ID 797860", "ID 806559", "ID 810517", "ID 826054", "ID 837609", 
    "ID 839287", "ID 867918", "ID 869788", "ID 875380", "ID 876870", 
    "ID 882220", "ID 893116", "ID 895909", "ID 899050", "ID 900143", 
    "ID 908100", "ID 912185", "ID 916371", "ID 916620", "ID 957879", 
    "ID 966195", "ID 993247", "ID 998911", "ID 999610"), class = "factor"), 
        region = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L), location = c(259090L, 559306L, 2227063L, 2369217L, 4026978L, 
        4211264L, 4679449L, 5105226L, 5106345L, 5344670L, 5473601L, 
        5476528L, 5871970L, 6461228L, 6700029L, 6708265L, 7639959L, 
        9297695L, 10254788L, 10328812L, 11102816L, 11568295L, 11720437L, 
        12843457L, 14012506L, 14156669L, 14632300L, 14641938L, 15298211L, 
        15468425L, 15534406L, 16279682L, 16699353L, 17226952L, 17320785L, 
        269017L, 453097L, 828833L, 954610L, 954842L, 1066378L, 1217332L, 
        1253530L, 1277716L, 1292857L, 1337952L, 1439657L, 1452989L, 
        1712345L, 1758035L, 2601630L, 2640359L, 2778095L, 3151129L, 
        3369931L, 3399080L, 3529525L, 3810217L, 3821120L, 3841588L, 
        3901557L, 4111633L, 4220440L, 4528632L, 4665450L, 5099307L, 
        5260242L, 5958770L, 5966356L, 6137405L, 6246065L, 6297231L, 
        6807949L)), .Names = c("id", "region", "location"), class = "data.frame", row.names = c(NA, 
    -73L)) 
    
  2. 두 샘플 입력

샘플 1

0,123,516 실행 Rprof
 structure(list(region = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), 
     begin = c(0L, 2259252L, 5092077L, 9158205L, 0L, 135094L, 
     941813L, 5901391L, 6061324L), finish = c(2259252L, 5092077L, 
     9158205L, 20463033L, 135094L, 941813L, 5901391L, 6061324L, 
     7092402L), sed = c(3.98106154985726, 7.51649828394875, 5.15440228627995, 
     2.67456624889746, 7.54309412557632, 4.17413910385221, 7.47043058509007, 
     6.13362524658442, 1.00084994221106)), .Names = c("region", 
     "begin", "finish", "sed"), class = "data.frame", row.names = c(NA, 
     -9L)) 

샘플 2

 structure(list(region = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), 
     begin = c(0L, 2253252L, 7091077L, 9120205L, 0L, 135094L, 
     941813L, 5901391L, 6061324L), finish = c(2253252L, 7091077L, 
     9120205L, 17463033L, 135094L, 941813L, 5901391L, 6061324L, 
     7092402L), sed = c(3.31830840984048, 1.38014704208403, 6.13049140975458, 
     2.10349875097134, 0.48170587509345, 0.13058713509175, 9.13509713513509, 
     6.13047153058701, 3.81734081501503)), .Names = c("region", 
     "begin", "finish", "sed"), class = "data.frame", row.names = c(NA, 
     -9L)) 

Unvectorized 코드

matchLocationsToRegions <- function(path) {  
# get list of data files (around 500 of these; only dput of 2 given: sample262519 and sample252519) 
setwd(path,sep="",collapse=NULL) 
data_files <- list.files() 

# read in template file with complete regional boundaries 
standRef <- read.table(paste(path, "StandRef.txt",sep="",collapse=NULL), header=TRUE, sep="\t") 

# pre-allocate a df with row dimensions of standRef and num of columns according to num of data files 
sediment.df <- as.data.frame(matrix(NA,nrow=nrow(standRef),ncol=length(data_files))) 
colnames(sediment.df) <- data_files 
rownames(sediment.df) <- standRef[,1] 

# create a counter for columns filled 
col_counter <- 1  

for (file in data_files) { 
    # read in current, processed data 
    sample <- read.table(file, header=TRUE, sep="\t")   

    # pre-allocate vectors for sedimentation data vector 
    sed <- rep(NA, nrow(standRef)) 

    # create a variable to track end boundary for a particular sample_ID 
    end_tracker <- 1 

    index <- unlist(lapply (unique(standRef$region), function(reg) { 
      reg.filter <- which(standRef$region == reg) 
      samp.filter <- which(sample$region == reg) 
      samp.filter[cut(standRef$location[reg.filter],c(0L,sample$finish[samp.filter]),labels=F)] 
     })) 
    sed <- sample$sed[index] 

    # fill in next, unfilled column of relevant df with data from relevant vector 
    sediment.df[col_counter] <- sed 

    # update column counter variable 
    col_counter <- col_counter + 1 
}  

# save df as a table 
write.table(sediment.df,file="samples_sed.txt", row.names=TRUE, sep="\t") 
} 

"scan" "read.table" "matchLocationsToRegions""type.convert" "read.table" "matchLocationsToRegions" 런타임을 우세 것으로 나타났다. 아마도에 대한 루핑이 선 이상에 의한 병목 현상이있다 :

sample <- read.table(file, header=TRUE, sep="\t")  

업데이트 : 지역에 걸쳐 for 루프가 훨씬 빠른 실행 코드 (H/t 사이먼 Urbánek의)로 대체되었습니다. 그러나 나머지는 아주 느립니다.

+0

먼저 'Rprof()'를 실행하고 병목이 어디에 있는지 확인하는 것이 좋습니다. –

+0

@ RomanLuštrik'Rprof '에서 몇 가지 정보를 추가했습니다. – Kaleb

+0

통계 SE를 시도해보십시오. R에 기술이있는 사람들이 꽤 있습니다. – check123

답변

1

쉽게 루프 제거 할 수 있습니다 그러나

sediment.df <- as.data.frame(lapply(data_files, function(file) { 
    sample <- read.table(file, header=TRUE, sep="\t")   
    index <- unlist(lapply (unique(standRef$region), function(reg) { 
     reg.filter <- which(standRef$region == reg) 
     samp.filter <- which(sample$region == reg) 
      samp.filter[cut(standRef$location[reg.filter],c(0L,sample$finish[samp.filter]),labels=F)] 
    })) 
    sample$sed[index] 
})) 
colnames(sediment.df) <- data_files 
rownames(sediment.df) <- standRef[,1] 

, 그래서 당신은, scan 사용)을 고려할 수 많은 시간이 read.table에 소요되는하지 않을 B) 모두와 하나 개의 파일을 생성 샘플 (예 : 샘플을 정의하기 위해 여분의 열을 사용)을 사용하면 많은 파일을로드 할 필요가 없습니다.

+0

필자는 이것이 문제가 아니라는 것을 알고 있지만'sample $ sed [index]'뿐만 아니라'sample $ borewidth [index]'를 반환하고 그것을 자체 데이터 프레임에 넣어야한다면 (예를 들어'borewidth.df'), 별도의 'as.data.frame (lapply ...'구조체를 다시 만들지 않고도이 작업을 어떻게 수행 할 것인가? 샘플 파일을 두 번 실행해야하므로 좋지 않다. 하나를 만들고 샘플을 집계한다. 파일이 다양하기 때문에 파일이 실제로 가능하지 않습니다. 감사합니다. – Kaleb

+1

하나 이상의 벡터 결과를 사용하면 편리함을 잃어 버립니다. 예를 들어 하나의 벡터 대신에 매트릭스를 반환 할 수 있지만 모든 열을 두 개로 나눕니다. (다른 여러 가지 방법도 있습니다.) 집계 파일의 경우, 무엇을 의미합니까?고정 열을 사용하므로 원본 파일을 나타내는 별도의 ID 열이있는 하나의 파일에 넣을 수 있습니다. –

+0

하나의 집합 파일을 가질 수 있다고 가정합니다. 하지만 "sourceid" "region" "begin" "finish" "sed" "borewidth"'columns x 500 (3000 cols)을 의미합니까, 아니면 당신을 오해하고 있습니까? 메모리에 문제가 있습니까? – Kaleb

관련 문제