цикл для создания нескольких матриц в R (возможно, с использованием вставки)

Я хочу создать матрицу 27 с 2 столбцами и переменным количеством строк. Я мог бы просто написать 27 строк кода, например:

 x1 = cbind(rep(1,34), rnorm(34))

 x2 = cbind(rep(1,36), rnorm(36))

....

x27 = cbind(rep(1,k), rnorm(k))

Но у него должен быть лучший способ сделать это. Я думал о цикле, что-то вроде этого:

aux = c(34, 36, ..., k) # auxiliar variable with number of rows for each matrix

for (i in 1:27) paste("x",i, sep="") =  cbind(rep(1,aux[i]), rnorm(aux[i]))

Однако это не работает. Я чувствую, что это простая задача, но у меня нет идей.

Любая помощь?

пс.: Я думал о массиве, но не смог его использовать. Может быть, список может сделать работу, я не знаю.


person Manoel Galdino    schedule 04.02.2011    source источник
comment
Мне кажется важным создать 27 объектов R (x1, x2, x3,..., x27)   -  person Manoel Galdino    schedule 04.02.2011
comment
поищите ответ @Joshua Ulrich, так как я чувствую, что мог неправильно понять ваш вопрос. Если вам нужны отдельные матрицы, а не объединенные в список, то зеленая галочка должна перейти к нему.   -  person daroczig    schedule 04.02.2011
comment
Оба решения будут работать. Спасибо всем, и я отметил ваш ответ (@daroczig), потому что он сработал для меня.   -  person Manoel Galdino    schedule 05.02.2011


Ответы (4)


Вам нужно assign:

for (i in 1:27) {
  assign(paste("x",i,sep=""), cbind(rep(1,aux[i]), rnorm(aux[i])))
}

Это создаст 27 матричных объектов в вашей глобальной среде.

person Joshua Ulrich    schedule 04.02.2011

Если вам нужно другое количество строк, вам обязательно нужно использовать список. См. пример ниже:

Во-первых, объявите свою переменную aux, которая содержит количество строк для генерации:

aux <- 50:77

И пусть ваш цикл вращается:

x <- vector("list",27) 
for (i in 1:27) {
    x[[i]] <- cbind(rep(1,aux[i]), rnorm(aux[i]))
}

Что вернет список ваших кадров данных. См., например. str(x) для списка и str(x[[1]]) для структуры первой матрицы. Последний вернется:

 num [1:50, 1:2] 1 1 1 1 1 1 1 1 1 1 ...

И вы правы: его можно было бы написать намного красивее, чем это предложение, ищите lapply и так далее, но с этой сложной частью вам помогут другие :)


После редактирования: добавлен lapply пример

Попробуйте приведенный ниже код, если вы знакомы с приведенным выше циклом (и, конечно же, ищите ?lapply):

aux <- 50:77
fun <- function(x) cbind(rep(1,x), rnorm(x))
x <- lapply(aux, fun)
person daroczig    schedule 04.02.2011
comment
Но разве вам не нужно сначала создать x? что-то вроде x ‹- list() или x ‹- vector()? Мой компьютер не нашел объект x. - person Manoel Galdino; 04.02.2011
comment
Да, нам нужно сначала создать x . Спасибо большое. Я использовал просто x ‹- list() - person Manoel Galdino; 04.02.2011
comment
@Manoel Galdino: да, извините за эту ошибку! Я отредактировал свой ответ и добавил дополнительную строку, а также добавил пример с lapply, чтобы взамен сделать решение более аккуратным :) - person daroczig; 04.02.2011
comment
Предварительно выделить! Определите x <- vector("list",27) перед циклом, затем установите каждый элемент x внутри цикла. Это намного эффективнее, чем расширять список для каждой итерации. - person Joshua Ulrich; 04.02.2011
comment
@ Джошуа Ульрих: правда, спасибо, что указали - это действительно полезно. Я отредактировал свой ответ, чтобы сделать его лучше. И я только что (прочитав ваш ответ) понял, что, возможно, тоже неправильно понял вопрос :( - person daroczig; 04.02.2011
comment
@daroczig: Сказав, что это намного эффективнее, я решил проверить свое утверждение. Это лишь незначительно эффективнее, но все же это хорошая практика. ;-) - person Joshua Ulrich; 04.02.2011

Если вы ничего не имеете против списков, вот еще один ответ на ваш вопрос:

aux <- 30:40
manoel <- sapply(aux, function(x) {
            matrix(NA, ncol = 2, nrow = x)
        }, simplify = FALSE)

> str(manoel)
List of 11
 $ : logi [1:30, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:31, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:32, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:33, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:34, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:35, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:36, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:37, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:38, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:39, 1:2] NA NA NA NA NA NA ...
 $ : logi [1:40, 1:2] NA NA NA NA NA NA ...
person Roman Luštrik    schedule 04.02.2011

В приведенном ниже коде показано, как я использовал подход Джошуа Ульриха для создания немного более сложных матриц. Надеюсь, этот ответ будет полезен и покажет некоторую гибкость, возможную при создании объектов. Если нет, я могу удалить свой ответ.

Я подозреваю, что этот подход можно легко изменить для создания матриц, различающихся по размеру, например, установив nrow или ncol равным переменной и используя rep(q, z) с некоторой переменной z для дублирования элементов в векторе внутри оператора matrix или rbind:

p1.c1 <- 0.10
p2.c1 <- 0.20
p3.c1 <- 0.30
p4.c1 <- 0.40

s1.c1  <- matrix(c(p1.c1, p1.c1, (1 - p1.c1),
                   p1.c1, p1.c1, (1 - p1.c1),
                       0,     0,          1), nrow=3, ncol=3, byrow = TRUE)
s2.c1  <- matrix(c(p2.c1, p2.c1, (1 - p2.c1),
                   p2.c1, p2.c1, (1 - p2.c1),
                       0,     0,          1), nrow=3, ncol=3, byrow = TRUE)
s3.c1  <- matrix(c(p3.c1, p3.c1, (1 - p3.c1),
                   p3.c1, p3.c1, (1 - p3.c1),
                       0,     0,          1), nrow=3, ncol=3, byrow = TRUE)
s4.c1  <- matrix(c(p4.c1, p4.c1, (1 - p4.c1),
                   p4.c1, p4.c1, (1 - p4.c1),
                       0,     0,          1), nrow=3, ncol=3, byrow = TRUE)

n <- 5

p.c1 <- c(p1.c1, p2.c1, p3.c1, p4.c1)

for (i in 1: (n - 1)) {
  assign(paste('xs', i, '.c1', sep=""), matrix(c(p.c1[i], p.c1[i], (1-p.c1[i]),
                                                 p.c1[i], p.c1[i], (1-p.c1[i]),
                                                       0,       0,         1 ), nrow=3, ncol=3, byrow = TRUE))
}
identical(xs1.c1, s1.c1)
identical(xs2.c1, s2.c1)
identical(xs3.c1, s3.c1)
identical(xs4.c1, s4.c1)

for (i in 1: (n - 1)) {
  assign(paste('ys', i, '.c1', sep=""), rbind(c(p.c1[i], p.c1[i], (1-p.c1[i])),
                                              c(p.c1[i], p.c1[i], (1-p.c1[i])),
                                                    c(0,       0,          1)))

}
identical(ys1.c1, s1.c1)
identical(ys2.c1, s2.c1)
identical(ys3.c1, s3.c1)
identical(ys4.c1, s4.c1)
person Mark Miller    schedule 01.03.2018