2014-10-13 3 views
1

많은 수의 반복에 대해 시뮬레이션 기능을 실행하는 프로그램이 있습니다. 그러나 나는 가장 쉬운 부분이 될 것으로 기대되는 것에 매달 렸습니다 : 함수 결과의 빈도 수를 저장하는 방법을 알아 냈습니다.시뮬레이션 함수의 빈도수 저장 R

시뮬레이션 기능 자체는 복잡하지만 R의 sample() 기능과 유사합니다. 많은 양의 데이터가 입력되고이 함수는 요소의 하위 집합을 포함하는 벡터를 출력합니다.

x <- c("red", "blue", "yellow", "orange", "green", "black", "white", "pink") 

run_simulation <- function(input_data, iterations = 100){ 
    for (i in 1:iterations){ 
    result <- sample(input_data, 3, replace=FALSE) 
    results <- ???? 
    } 
} 

run_simulation(x) 

내 질문은 시뮬레이션 루프 내부의 함수의 결과의 주파수 카운트를 저장하는 가장 좋은 (가장 효율적이고 R-같은) 데이터 구조가 무엇인지입니다. , 거기 그러나

counts[results_tuple] = counts.get(results_tuple, 0) + 1 

: 당신이 for 루프에서 말할 수있을 때, 나의 배경은 내가 특정 조합이 출력 될 때마다 증가 튜플에 의해 키가 사전인가를 만들 것입니다 파이썬, 같은 언어에 R에 상응하는 dict/hashmap 타입 구조가 없으며, R에서 다른 언어를 에뮬레이션하려고하면 추악하고 비효율적 인 코드를 만드는 방법이라는 것을 자주 발견했습니다. (지금은 출력 벡터를 문자열로 변환하고 나중에 숫자가 table() 인 결과 목록에 추가했지만 가능한 출력 벡터의 수가 제한된 함수에 비해 반복 횟수가 많으면 메모리가 비효율적입니다. .

   Result Freq 
    black, pink, green 8 
    blue, red, white 7 
    black, pink, blue 7 
    blue, green, black 5 
    blue, green, red 4 
    green, blue, white 3 
    pink, green, white 3 
    white, blue, green 1 
    white, orange, red 1 
yellow, black, orange 1 
    yellow, blue, green 1 

내가 어떤 특정 요소의 주파수 만 세트에 대해 걱정하지 않는다 :)

것은 명확하게하기 위해, 여기에 내가 원하는 출력의 종류이다. 그리고 나는 출력의 순서에 관심이 없다. 단지 주파수이다.

아무쪼록 감사드립니다.

+0

답변을 게시하면 즉시 귀하의 설명에 있음을 알 수 있습니다. 너무 독창적이지 않다! 그리고, 게시물을 더 자세히 읽어야합니다 ... 어쨌든, 응답이 삭제되었습니다. 내가 원래의 방법으로 올 경우 다시 게시됩니다. – ddiez

답변

1

실제로는 해시 테이블을 사용하는 environment을 사용할 수도 있습니다.

runSimulation <- function(input.size = 300L, iterations = 100L) { 
    x <- paste0("E", 1L:input.size) 
    results <- new.env(hash = TRUE) 
    for (i in 1:iterations){ 
     result <- sample(x, 3, replace = FALSE) 
     nam <- paste0(sort(result), collapse = ".") 
     if (exists(nam, results)) { 
     results[[nam]] <- results[[nam]] + 1 
     } else { 
     assign(nam, 1, envir = results) 
     } 
    } 
    l <- as.list(results) 
    d <- data.frame(tuple = names(l), count = unlist(l)) 
    rownames(d) <- NULL 
    d 
} 

그러나,이 table를 사용하여 솔루션에 필적 감마값 : 당신은 어쨌든 카운트 단지 관심으로 이러한 방법으로 시뮬레이션의 모든 결과를 열거 할 필요는 없다.

+0

이것은 정확히 내가 원하는 것입니다. 입력 데이터의 크기를 고려할 때 가능한 모든 결과를 사전 계산하지 않아야합니다. – BringMyCakeBack

1

가능한 값을 키로 사용하는 data.table (구현 된 최대 농축액 data.frame)을 사용할 수 있습니다. 그들은 특정한 문법을 ​​요구하지만, 매우 효율적입니다.

다음은 어떻게 진행할까요? 다시 인덱스에 대한 시뮬레이션 출력을 일치하는 것은 그것을 정렬이 필요합니다, 그래서 새로운 변수 아래에 저장된 :

require(data.table) 

x <- c("red", "blue", "yellow", "orange", "green", "black", "white", "pink") 

run_simulation <- function(input_data, iterations = 100){ 

    # generate set of all possible outputs 
    possible_values <- sort(input_data) ## needed to match simulations 

    # combn() seems to preserve input order 
    # have to sort each column from combn() output if this is not guaranteed 
    results <- as.data.table(t(combn(possible_values, 3))) 
    setnames(results, c("first", "second", "third")) 
    results[, count:=0] ## initiate counts column 
    setkey(results, first, second, third) ## use index columns as table key 

    for (i in 1:iterations){ 
    result <- sample(input_data, 3, replace=FALSE) 
    result_sorted <- t(sort(result)) ## t() needed to specify it's a row 
    colnames(result_sorted) <- c('first', 'second', 'third') 
    result_sorted <- as.data.table(result_sorted) 
    results[result_sorted, count:=count + 1] 
    } 
    return(results) 
} 

라인의 대부분의 세대가 올바른을 찾아 볼 data.table에 적합한 형식으로 벡터를 얻을 필요 후 열. 가능한 조합의 수가 적 으면 잔인 할 수도 있지만 가능한 세트가 클 경우 배당금을 지불해야합니다.

+0

대단하군요. 한 가지 질문 : 모든 가능한 조합으로 data.table을 채우지 않는 방법이 있습니까? (즉,'results <- as.data.table (t (combn (possible_values, 3)))'). 결과는 실제로 많은 가능성이 있지만 시뮬레이션 함수는 가능한 결과물. 아마도 if (! exists (results [result_sorted])) {results [result_sorted] $ count <- 0}' – BringMyCakeBack

+0

그럴 수도 있지만 바람직하지는 않습니다 .R에서는 크기를 미리 할당하는 것이 좋습니다 (변수는 연속적인 메모리를 필요로합니다.) 0을 원하지 않으면, 다음과 같이 끝내면 제거하는 것이 좋습니다 :'return (results [count> 0])' – ilir

+0

할당을 실현했습니다. 'current_count'는 필요하지 않았고 라인을 제거했습니다. – ilir

1

다음은 매우 빠른 실행 시간을 제공하는 기본 R을 사용하는 간단한 솔루션입니다.

run_simulation <- function(input_data, iterations = 100){ 
Results <- replicate(iterations, paste0(sort(sample(input_data, 3, replace=FALSE)),collapse=", ") ) 
results <- as.data.frame(table(Results)) 
} 

run_simulation는 (x)이 100, 1,000, 10,000 및 100,000의 반복에 대한 시간은 바람직 보인다 반복 횟수에 따라 선형 적으로 증가하는 것이 도시 벤치마킹

    Results Freq 
1  black, blue, green 2 
2 black, blue, orange 2 
3  black, blue, pink 6 
4  black, blue, red 6 
5  black, blue, white 2 
6 black, green, orange 3 
7  black, green, pink 1 
8  black, green, red 1 

을 준다. 또한 100,000 반복의 총 시간은 약 2,200 밀리 초 또는 2.2 초입니다. 많은 양의 데이터를 사용하여 시뮬레이션을 복잡하게 설명하므로 시뮬레이션을 수행하는 총 시간이 결과를 도표화하는이 비트 비트에 소요되는 시간을 훨씬 초과 할 수도 있습니다.

library(microbenchmark) 

microbenchmark(run_simulation(x,iterations=100), run_simulation(x,iterations=1000), run_simulation(x,iterations=10000), run_simulation(x,iterations=100000), times=100) 

Unit: milliseconds 
            expr   min   lq  median   uq  max neval 
    run_simulation(x, iterations = 100) 2.352262 2.447647 2.488282 2.573545 71.96314 100 
    run_simulation(x, iterations = 1000) 19.161997 19.751702 20.476572 24.411885 90.42650 100 
    run_simulation(x, iterations = 10000) 193.688216 208.453087 217.130138 226.166201 289.13177 100 
    run_simulation(x, iterations = 1e+05) 2012.773904 2125.986609 2169.870885 2236.038487 2426.02379 100