2010-07-07 7 views
3

Я застрял в простой петле, которая занимает больше часа, чтобы бежать, и нужна помощь, чтобы ускорить ее.Возвращаемое значение из столбца, указанного в той же строке

В принципе, у меня есть матрица с 31 столбцом и 400 000 строк. Первые 30 столбцов имеют значения, а 31-й столбец имеет номер столбца. Мне нужно, чтобы каждая строка извлекала значение в столбце, указанном 31-м столбцом.

Пример строки: [26,354,72,5987 .., 461,3] (это означает, что значение в колонке 3 желаемая (72))

Слишком медленная петля выглядит следующим образом:

a <- rep(0,nrow(data)) #To pre-allocate memory 
for (i in 1:nrow(data)) { 
    a[i] <- data[i,data[i,31]] 
} 

Я думаю, что это будет работать:

a <- data[,data[,31]] 

... но это приводит к «Ошибка: не может выделить вектор размером 2,8 Мб».

Я боюсь, что это очень простой вопрос, поэтому я потратил часы, пытаясь понять, применять, lapply, изменить форму, и больше, но почему-то я не могу получить контроль над концепцией векторизации в R.

В матрице фактически есть еще больше столбцов, которые также входят в параметр a, поэтому я не хочу перестраивать матрицу или разбить ее.

Ваша поддержка высоко оценена!

Крис

+1

Вы уверены, что имеется достаточная свободная оперативная память? – mbq

+1

применяются, и друзья не имеют ничего общего с векторией. – Shane

+0

Ваш пример создаст другую матрицу того же размера, что и ваш оригинал.Похоже, что у вас заканчивается RAM в вашей рабочей области - числовой вектор длиной 400000 занимает 3,1 Мб, а матрица должна занимать 94,6 Мб. – James

ответ

2
t(data[,1:30])[30*(0:399999)+data[,31]] 

Это работает, потому что вы можете ссылаться как в матрицах, формате массив и векторный формат (длинный вектор 400000 * 31 в данном случае) подсчет столбцы первыми. Чтобы подсчитать поровну, вы используете транспонирование.

0

Индексный индекс для матрицы может использовать меньше памяти. Это потребовало бы делать что-то вроде:

i <- nrow(data)*(data[,31]-1) + 1:nrow(data) 
a <- data[i] 

Ниже приведен пример одноиндексного обозначения для матриц в R. В этом примере, индекс максимума за строку добавляются в последнем столбце случайной матрицы , Затем этот последний столбец используется для выбора максимумов каждой строки с помощью одноиндексной нотации.

## create a random (10 x 5) matrix                               
M <- matrix(rpois(50,50),10,5) 
## use the last column to index the maximum value of the first 5                        
## columns                                     
MM <- cbind(M,apply(M,1,which.max)) 
##    column ID   row ID                              
i <- nrow(MM)*(MM[,ncol(MM)]-1) + 1:nrow(MM) 
all(MM[i] == apply(M,1,max)) 

Использование index matrix является альтернативой, которая, вероятно, использовать больше памяти, но немного понятнее:

ii <- cbind(1:nrow(MM),MM[,ncol(MM)]) 
all(MM[ii] == apply(M,1,max)) 
0

Попробуйте изменить код для работы колонки в то время:

M <- matrix(rpois(30*400000,50),400000,30) 
MM <- cbind(M,apply(M,1,which.max)) 
a <- rep(0,nrow(MM)) 
for (i in 1:(ncol(MM)-1)) { 
    a[MM[, ncol(MM)] == i] <- MM[MM[, ncol(MM)] == i, i] 
} 

Это устанавливает все элементы в a со значениями из столбца i, если последний столбец umn имеет значение i. Потребовалось больше времени для построения матрицы, чем для вычисления вектора a.