Как использовать применение вместо цикла for для функции stringMatch?

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

library(MiscPsycho)
b <- c("-BC", "ACB", "---") # Toy example of sequences
workb <- expand.grid(b,b)
new <- c(1:9)

# Need to get rid of this for loop somehow
for (i in 1:9) {
new[i] <- stringMatch(workb[i,1], workb[i,2], normalize="NO")
}

workb <- cbind(workb, new)
newmat <- reShape(workb$new, id=workb$Var1, colvar=workb$Var2)

a <- c("Subject1", "Subject2", "Subject3") #Relating it back to the subject ID
colnames(newmat) <- a
rownames(newmat) <- a
newmat

Я не очень хорошо знаком с использованием функций применения, но я хотел бы использовать его, чтобы иметь возможность заменить цикл for, который, вероятно, будет медленным, учитывая, что у меня большое количество последовательностей. (Функция stringMatch взята из MiscPsycho). Пожалуйста, подскажите, как сделать его более эффективным!

Большое спасибо!


person Jennifer Collins    schedule 19.06.2012    source источник
comment
Есть ли способ сделать код более эффективным? Различные решения, приведенные ниже, хорошо работают для коротких последовательностей, но у меня есть несколько сотен последовательностей, и я пытаюсь построить для них матрицу попарных разностей, и каждая последовательность имеет одинаковую длину (около 300 символов). Когда я использую приведенный ниже код, на создание матрицы, сравнивающей 20 последовательностей, уходит более получаса...   -  person Jennifer Collins    schedule 08.07.2012


Ответы (3)


Чтобы получить эти «парные расстояния», я бы сделал что-то вроде:

  Vm <- Vectorize(stringMatch)
  nex <- outer(b,b, FUN=Vm, normalize = "NO")
 nex
     [,1] [,2] [,3]
[1,]    0    3    2
[2,]    3    0    3
[3,]    2    3    0
person IRTFM    schedule 19.06.2012
comment
Я думаю об этом только тогда, когда получаю такие сообщения: Error in outer(b, b, FUN = stringMatch) : dims [product 9] do not match the length of object [1] - person IRTFM; 20.06.2012
comment
Большое спасибо!! Это прекрасно работает, и это намного эффективнее, чем то, что было у меня. - person Jennifer Collins; 20.06.2012

Для замены петли

new <- apply(workb, 1, function(x) stringMatch(x[[1]],x[[2]], normalize="NO"))
person Maiasaura    schedule 19.06.2012
comment
Большое спасибо!! Это то, что я надеялся написать, но я просто запутался в синтаксисе. - person Jennifer Collins; 20.06.2012

Я бы сделал функцию, которая берет ваш индекс i и возвращает new[i].

myfun <- function(i) {
  stringMatch(workb[i, 1], workb[i, 2], normalize='NO')
}

Затем вы можете apply вдоль нового вектора:

workb$new <- unlist(lapply(new, myfun))

В общем, вы правильно используете for loop в R. Вы заранее выделили вектор new и заполняете его, а не увеличиваете.

person Justin    schedule 19.06.2012