Более быстрый код в R - PullRequest
       13

Более быстрый код в R

6 голосов
/ 07 марта 2012

К вашему сведению: я значительно отредактировал это с момента своего первого издания.Это моделирование было сокращено с 14 часов до 14 минут.

Я новичок в программировании, но я провел моделирование, которое пытается отслеживать бесполую репликацию в организме и количественно определять различия в количестве хромосом междуродительские и дочерние организмы.Симуляция работает очень медленно.Это займет около 6 часов.Я хотел знать, как лучше всего ускорить симуляцию.

У этих цифровых организмов х число хромосом.В отличие от большинства организмов, хромосомы все независимы друг от друга, поэтому они имеют равные шансы на передачу в любой дочерний организм.

В этом случае распределение хромосом в дочернюю клетку следует биномиальному распределению с вероятностью 0,5.

Функция sim_repo берет матрицу цифровых организмов с известным количеством хромосом и проводит их через 12 поколений репликации.Он дублирует эти хромосомы, а затем использует функцию rbinom для случайного генерирования числа.Этот номер затем присваивается дочерней ячейке.Поскольку никакие хромосомы не потеряны во время бесполого размножения, другая дочерняя клетка получает оставшиеся хромосомы.Затем это повторяется для G количества поколений.Затем из каждой строки в матрице отбирается одно значение.

 sim_repo = function( x1, G=12, k=1, t=25, h=1000 ) {

            # x1 is the list of copy numbers for a somatic chromosome
            # G is the number of generations, default is 12
            # k is the transfer size, default is 1
            # t is the number of transfers, default is 25
            # h is the number of times to replicate, default is 1000

            dup <- x1 * 2 # duplicate the initial somatic chromosome copy number for replication
            pop <- 1 # set generation time
            set.seed(11)
            z <- matrix(rbinom(n=rep(1,length(dup)),size = as.vector(dup),prob = 0.5),nrow = nrow(dup)) # amount of somatic chromosome is distributed to one of the daughter cells
            z1 <- dup - z # as no somatic chromosomes are lost, the other daughter cells receives the remainder somatic chromosomes
            x1 <- cbind(z, z1) # put both in a matrix

            for ( pop in 1:G ) { # this loop does the replication for each cell in each generation
                pop <- 1 + pop # number of generations.  This is a count for the for loop
                dup <- x1 * 2 # double the somatic chromosomes for replication
                set.seed(11)
                z <- matrix(rbinom(n=rep(1,length(dup)),size = as.vector(dup),prob = 0.5),nrow = nrow(dup)) # amount of somatic c hromosomes distributed to one of the daughter cells
                z1 <- dup - z # as no somatic chromosomes are lost, the other daughter cells receives the remainder somatic chromosomes
                x1 <- cbind(z, z1) # put both in a matrix
                }

            # the following for loop randomly selects one cell in the population that was created
            # the output is a matrix of 1 column
            x1 <- matrix(apply(x1, 1, sample, size=k), ncol=1)
            x1
    }

В моем исследовании меня интересует изменение дисперсии в хромосомах исходных исконных организмов и конечной временной точки в этом моделировании.Следующая функция представляет собой перенос клетки в новую среду обитания.Он берет вывод из функции sim_re p и использует его для генерации большего количества поколений.Затем он находит дисперсию между строками в первом и последнем столбцах матрицы и находит разницу между ними.

    # The following function is mostly the same as I talked about in the description.
    # The only difference is I changed some aspects to take into account I am using
    # matrices and not lists.
    # The function outputs the difference between the intial variance component between
    # 'cell lines' with the final variance after t number of transfers

sim_exp = function( x1, G=12, k=1, t=25, h=1000 ) {

    xn <- matrix(NA, nrow(x1), t)  
    x <- x1
    xn[,1] <- x1
    for ( l in 2:t ) {
        x <- sim_repo( x, G, k, t, h )
        xn[, l] <- x
    }

    colvar <- matrix(apply(xn,2,var),ncol=ncol(xn))
    ivar <- colvar[,1]
    fvar <- colvar[,ncol(xn)]
    deltavar <- fvar - ivar
    deltavar
}  

Мне нужно повторить эту симуляцию ч количество раз.Таким образом, я сделал следующую функцию, которая будет вызывать функцию sim_exp ч несколько раз.

sim_1000 = function( x1, G=12, k=1, t=25, h=1000 ) {
    xn <- vector(length=h)
    for ( l in 2:h ) {
        x <- sim_exp( x1, G, k, t, h )
        xn[l] <- x
    }
        xn
}

Когда я вызываю функцию sim_exp со значением наподобие 6, требуется около 52секунд до завершения.

 x1 <- matrix(data=c(100,100,100,100,100,100),ncol=1)
 system.time(sim_1000(x1,h=1))
   user  system elapsed 
  1.280   0.105   1.369 

Если я смогу получить его быстрее, то смогу завершить больше этих симуляций и применить модель выбора к симуляции.

Мой ввод будет выглядеть следующим образом x1, aматрица с каждым исконным организмом в отдельном ряду:

x1 <- matrix(data=c(100,100,100,100,100,100),ncol=1) # a matrix of 6 organisms

Когда я бегу:

a <- sim_repo(x1, G=12, k=1)

Мой ожидаемый результат будет:

 a
     [,1]
[1,]  137
[2,]   82
[3,]   89
[4,]  135
[5,]   89
[6,]  109

 system.time(sim_repo(x1))
   user  system elapsed 
  1.969   0.059   2.010 

Когда я позвонюфункция sim_exp,

b <- sim_exp (x1, G = 12, k = 1, t = 25) </p>

вызывает функцию sim_repo G раз и выдает:

 b
[1] 18805.47

Когда я вызываю функцию sim_1000, я обычно устанавливаю h на 1000, но здесь я установлю его на 2. Так что здесь sim_1000 будет вызывать sim_exp и дублировать его 2 раза.

c <- sim_1000(x1, G=12, k=1, t=25, h=2)
c
[1] 18805.47 18805.47

1 Ответ

8 голосов
/ 07 марта 2012

Как уже упоминалось другими в комментариях, если мы посмотрим только на функцию sim_repo и заменим строку:

dup <- apply(x1, c(1,2),"*",2)

с

dup <- x1 * 2

строк

z <- apply(dup,c(1,2),rbinom,n=1,prob=0.5)

с

z <- matrix(rbinom(n=rep(1,length(dup)),size = as.vector(dup),prob = 0.5),nrow = nrow(dup))

и внутренний цикл for с

x1 <- matrix(apply(x1,1,sample,size = 1), ncol=1)

Я получаю, ну, большое увеличение скорости:

system.time(sim_exp(x1))
   user  system elapsed 
  0.655   0.017   0.686 
> system.time(sim_expOld(x1))
   user  system elapsed 
 21.445   0.128  21.530 

И я убедился, что он делает то же самое:

set.seed(123)
out1 <- sim_exp(x1)

set.seed(123)
out2 <- sim_expOld(x1)

all.equal(out1,out2)
> TRUE

И это даже не вникает в предварительное распределение, которое может быть сложным без полного изменения дизайна, учитывая то, как вы структурировали свой код.

И это даже не начало , чтобы посмотреть, действительно ли вам нужны все три функции ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...