Эффективно опробовать рамку данных, избегая циклов

У меня есть кадр данных, который состоит из первого столбца (experiment.id), а остальные столбцы - значения, связанные с этим идентификатором эксперимента. Каждая строка является уникальным идентификатором эксперимента. В моем кадре данных есть столбцы порядка 10⁴ - 10⁵.

data.frame(experiment.id=1:100, v1=rnorm(100,1,2),v2=rnorm(100,-1,2) )

Этот кадр данных является источником моего пространства выборки. То, что я хотел бы сделать, - это для каждого уникального эксперимента. (Строка) случайным образом выборка (с заменой) одного из значений v1, v2, ...., v10000, связанных с этим id, и построения образца s1. В каждом образце s1 представлены все идентификаторы эксперимента.

В конце концов я хочу выполнить 10⁴ выборок, s1, s2, ...., s 10⁴ и рассчитать некоторую статистику.

Каким будет наиболее эффективный способ (вычислительно) выполнить этот процесс выборки. Я бы хотел как можно больше избегать циклов.

Update: My questions in not all about sampling but also storing the samples. I guess my real question is if there is a quicker way to perform the above other than

d<-data.frame(experiment.id=1:1000, replicate (10000,rnorm(1000,100,2)) )
results<-data.frame(d$experiment.id,replicate(n=10000,apply(d[,2:10001],1,function(x){sample(x,size=1,replace=T)})))
1
nl ja de
experiment.id - любая уникальная символьная строка/номер
добавлено автор ECII, источник
@John Спасибо за ваш вклад. Моя основная проблема, как вы упоминаете, - это время и хранение вычислений, а не сама процедура выборки. Вычисление статистики «на лету» было бы вариантом, но было бы полезно иметь полный набор данных заранее и делать анализы post hoc. Спасибо за ваш вклад.
добавлено автор ECII, источник
replicate и apply являются, по существу, циклическими и медленными. Любой из ответов, опубликованных до сих пор, будет быстрее, если у вас есть возможность хранить такую ​​матрицу. Если пространство становится проблемой, вам нужно будет перебрать строки и вывести статистику из них по ходу дела. Итак, цифра, что часть заранее. До сих пор вы подразумевали, что вам нужны значения 1e9. Это входит в матрицу с несколькими гигабайтами.
добавлено автор John, источник

3 ответы

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

Для фрейма данных d :

d[matrix(c(seq(nrow(d)), sample(ncol(d)-1, nrow(d), replace=TRUE)+1), ncol=2)]

Это один образец. Чтобы получить образцы N , просто умножьте выделение (как в ответе Джона):

mm <- matrix(c(rep(seq(nrow(d)), N), sample(ncol(d)-1, nrow(d)*N, replace=TRUE)+1), ncol=2)

result <- matrix(d[mm], ncol=N)

Но у вас будут проблемы с памятью.

3
добавлено
Благодарю. Ваша первая строка создает образец. Однако я хотел бы построить и сохранить 10⁴ этих образцов, а затем выполнить некоторые статистические данные. Что было бы эффективным для создания и хранения этого большого количества образцов?
добавлено автор ECII, источник
Сохраните все образцы в кадре данных для дальнейшего статистического анализа. См. Мое обновление моего вопроса и комментарий Джона.
добавлено автор ECII, источник
@ECII Сохраните его в переменной? В противном случае я не уверен, что вы просите.
добавлено автор Matthew Lundberg, источник

Самый короткий и наиболее читаемый IMHO по-прежнему должен использовать apply , но хорошо использует тот факт, что sample векторизован:

results <- data.frame(experiment.id = d$experiment.id,
                      t(apply(d[, -1], 1, sample, 10000, replace = TRUE)))

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

2
добавлено
Это может быть правильно? Вы производите каждую строку и возвращаете вектор. Как этот вектор вводится в результирующий фрейм?
добавлено автор ECII, источник
@ECII, t (apply (...)) вернет матрицу 1000 на 10000, которая будет привязана к идентификаторам эксперимента с помощью data.frame . Попробуйте.
добавлено автор flodel, источник
Скорость этого будет зависеть от количества строк
добавлено автор John, источник

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

mat <- as.matrix(datf[,-1])
nr <- nrow(mat); nc <- ncol(mat)
sel <- sample( 1:nc, nr, replace = TRUE )
sel <- sel + ((1:nr)-1) * nc
x <- t(mat)[sel]
seldatf <- data.frame( datf[,1], x = x )

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

ns <- 10 # number of samples/row
sel <- sample(1:nc, nr * ns, replace = TRUE )
sel <- sel + rep(((1:nr)-1) * nc, each = ns)
x <- t(mat)[sel]
seldatf <- cbind( datf[,1],  data.frame(matrix(x, ncol = ns, byrow = TRUE)) )

It's possible that it's going to be a really big data frame if you're going to set ns <- 1e5 and you have lots of rows. You may have to watch running out of memory. I do a bit of unnecessary copying for readability reasons. You can eliminate that for memory, and speed because once you are using large amounts of memory you'll be swapping out other programs that are running. That is slow. You don't have to assign and save x, mat, or even sel. The result of not doing that would provide you about the fastest answer possible.

2
добавлено