2013-11-02 3 views
1

У меня есть 3 набора данных, которые я переставлял 10 раз. Каждая перестановка набора данных создает столбец из 3-х матриц (одна матрица на один набор данных). Эти 3 матрицы (m1, m2, m3) приведены в списке L. Я хотел бы допросить все возможные комбинации (10x10x10 = 1000) для каждой записи (в этом случае 4). Я использовал expand.grid предоставить все комбинации вызовов столбцов через 3 матриц в ряду другой матрицы M:R использование lapply & sapply для запроса списка матриц, содержащих перестановочные данные

M<-expand.grid(seq(1:10),seq(1:10),seq(1:10)) 

Вот мои данные в списке:

m1<-matrix(c(1,2,1,0,3,2,1,2,3,4),nrow=4, ncol=10) 
m2<-matrix(c(m1[1,]),nrow=4,ncol=10) 
m3<-matrix(c(m1[2,]),nrow=4,ncol=10) 
L<-list(m1, m2, m3) 

Можете ли вы помочь мне использовать do.call, cbind, lapply/sapply эффективно извлечь столбец координат из М опрашивать соответствующие столбцы в 3-х матриц, содержащихся в L и связать их в новую матрицу как таковой:

m.res<-for (i in 1:nrow(M) { "get" L[[1:3]][M[i,]] } 

Для i=1, m.res уступит:

1 1 2 
2 3 2 
1 3 4 
0 1 0 

Я ясно нужен учебник для lapply/sapply как это не должно быть это трудно.

+0

Я изменил 'test' на' M' в вашем коде. Если это не то, что вы намеревались, добавьте определение для 'test'. – nico

+0

+1 например, входные данные и желаемый выход. В следующий раз также покажите, что вы пробовали, и * как * это не сработало, и это будет прекрасный вопрос. –

+0

@ SimonO101 хорошо пункт! У меня нет моей .Rhistory на этом ноутбуке, но я помню, что я пробовал различные схемы, чтобы передать элементы из M непосредственно в L, чтобы подмножество нужных столбцов. Тогда я понял, что мне нужно использовать приложение – reviewer3

ответ

2

Прежде всего, мы должны получить правильный способ получения одной строки. Так, для линии 1 (1,1,1)

Мы хотим, чтобы петли по трем элементам L и получить матрицу с индексами строки 1 в M

col.ids <- unlist(M[1,]) 
# sapply will already return the columns in a matrix 
# We use seq_along rather than looping directly on L, because we also need the 
# id for col.ids 
sapply(seq_along(L), function(id){ 
         L[[id]][ ,col.ids[id] ] 
         }) 

    [,1] [,2] [,3] 
[1,] 1 1 2 
[2,] 2 3 2 
[3,] 1 3 4 
[4,] 0 1 0 

Теперь просто положить, что в другом заявлении apply, и вы настроены!

На этот раз мы используем применить, и цикл непосредственно над рядами M (тем самым устраняя необходимость в переменных col.ids)

# The second parameter is 1 for rows and 2 for columns 
m.comb <- apply(M, 1, function(cols) 
         { 
         sapply(seq_along(L), function(id){ 
               L[[id]][ ,cols[id] ] 
               }) 
         }) 

Теперь apply дает нам большую 12 х 1000 матрицы, которая очень раздражающий в этом случае, поэтому мы должны изменить его на список ... который я оставлю в виде упражнения для читателя ...

... или, скорее, использовать функцию 10, которая работает точно например apply, но всегда возвращает список (см. Force apply to return a list)

В этом случае, однако, мы должны unlist cols

library(plyr) 
m.comb.2 <- alply(M, 1, function(cols) 
         { 
         cols <- unlist(cols) 
         sapply(seq_along(L), function(id) 
           { 
           L[[id]][ ,cols[id] ] 
           }) 
         }) 

И, наконец ...

m.comb.2[[1]] 

    [,1] [,2] [,3] 
[1,] 1 1 2 
[2,] 2 3 2 
[3,] 1 3 4 
[4,] 0 1 0 

m.comb.2[[10]] 

    [,1] [,2] [,3] 
[1,] 1 1 2 
[2,] 2 3 2 
[3,] 3 3 4 
[4,] 4 1 0 
+0

Это прекрасно работает, и спасибо, что так хорошо объяснили! Я могу использовать пакет plyr в конце, но я сначала буду играть с принуждением m.comb в список (первое, что завтра :-) Это был очень полезный ответ, я бы хотел, чтобы я мог его продвигать более одного раза! – reviewer3

+0

Спасибо @nico тем временем, я посоветовал этот вопрос [6819804] (http://stackoverflow.com/questions/6819804/) использовать 'split()' для преобразования матрицы в список. Таким образом, я заканчиваю список из 1000 векторов (размер 4 * 3), который я мог бы обрабатывать с помощью надлежащего подмножества, однако ... – reviewer3

+0

... Теперь я понимаю, что у меня есть новая проблема: 24 набора данных x 34000 точек данных x 1000 shuffles x 8 bytes = 6.6 Gb только для перетасованных данных ... отсутствие свободной памяти. Вероятно, мне придется опубликовать это как отдельный вопрос. Ugh - теперь мне тоже нужно беспокоиться об управлении памятью. Во всяком случае, не совсем часть этого вопроса. – reviewer3

2

[Я хотел бы добавить, что, как комментарий к ответу @nico «ы, но я хотел, чтобы он был более чистым и расширенным, чем комментарий может быть. Если @nico считает полезным добавить его в свой подробный ответ, мой ответ следует удалить.]

Вы также можете использовать mapply, т. Е.вы можете применить функцию извлечения к нескольким аргументам (поскольку есть только 3 аргумента), которые у вас уже есть в M.

#`M` is your dataframe of arguments and `L` is your list of matrices 
#save all results to a list (`myls`) 
myls <- mapply(function(colmat1, colmat2, colmat3) 
       { cbind(L[[1]][,colmat1], L[[2]][,colmat2], L[[3]][,colmat3]) }, 
         M[,1], M[,2], M[,3], SIMPLIFY = F) 

myls[[1]] 
#  [,1] [,2] [,3] 
#[1,] 1 1 2 
#[2,] 2 3 2 
#[3,] 1 3 4 
#[4,] 0 1 0 
myls[[10]] 
#  [,1] [,2] [,3] 
#[1,] 1 1 2 
#[2,] 2 3 2 
#[3,] 3 3 4 
#[4,] 4 1 0 
+0

Хороший ответ! Я всегда стараюсь забыть «mapply» по какой-то причине :) – nico

+0

@alexis_laz Спасибо за это решение, но мне нужно что-то, что я могу без усилий масштабировать до количества перестановок. Я не включил эту информацию в вопрос, но я хочу перетасовать данные 100 или 1000 раз. Тем не менее это очень полезно, поскольку я раньше не использовал mapply! Спасибо! – reviewer3