R: Выборка в ячейки предопределенных размеров (вектор выборки разделения)

Я работаю над набором данных, состоящим из ~ 10 ^ 6 значений, которые сгруппированы в переменное количество ячеек. В ходе моего анализа я пытаюсь рандомизировать свою кластеризацию, но сохраняю постоянный размер ячейки. В качестве игрушечного примера (в псевдокоде) это будет выглядеть примерно так:

data <- list(c(1,5,6,3), c(2,4,7,8), c(9), c(10,11,15), c(12,13,14));
sizes <- lapply(data, length);
for (rand in 1:no.of.randomizations) {
    rand.data <- partition.sample(seq(1,15), partitions=sizes, replace=F)
}

Итак, я ищу такую ​​функцию, как «partition.sample», которая будет брать вектор (например, seq (1,15)) и случайным образом выбирать из него, возвращая список с данными, разделенными на правильные размеры ячеек, заданные уже " размеры".

Я пытался сам написать одну такую ​​функцию, так как задача кажется не такой уж сложной. Тем не менее, разбиение вектора на заданные размеры ячеек выглядит так, как будто это было бы намного быстрее и эффективнее, если бы оно выполнялось «под капотом», то есть, вероятно, не в родном R. Поэтому мне интересно, не пропустил ли я только что имя соответствующего функция, или может ли кто-нибудь указать мне умное решение, которое есть вокруг :-)

Ваша помощь и время очень ценятся! :-)

Лучший,

Лаймонд

ОБНОВЛЕНИЕ:

Под «n.of.randomizations» я подразумеваю фактическое количество раз, когда я прохожу весь «цикл рандомизации». Позже это, очевидно, будет включать в себя больше шагов, чем просто фактическая выборка.

Более того, я был бы также заинтересован в том, чтобы сделать описанный выше трюк для выборки без замены.

Заранее спасибо, ваша помощь очень ценится!


person Lymond    schedule 02.07.2012    source источник
comment
Вы оставили предполагаемое значение (и цель) no.of.randomizations довольно двусмысленным.   -  person IRTFM    schedule 02.07.2012
comment
Да я вижу. На самом деле я просто имею в виду количество рандомизаций, то есть сколько раз я запускаю цикл for для выполнения каких-либо вычислений (включая шаг partition.sample). Извини за это!   -  person Lymond    schedule 03.07.2012


Ответы (2)


Пересмотрено: это должно быть достаточно эффективным. Его сложность должна быть в первую очередь на этапе перестановки:

# A single step:
x <- sample( unlist(data)) 
list( one=x[1:4], two=x[5:8], three=x[9], four=x[10:12], five=x[13:16]) 

Как упоминалось выше, «n.of.randomizations» может быть количеством повторных применений этого процесса, и в этом случае вы можете захотеть обернуть это replicate:

replic <- replicate(n=4, { x <- sample(unlist(data))
   list( x[1:4], x[5:8], x[9], x[10:12], x[13:15]) }  )
person IRTFM    schedule 02.07.2012
comment
Спасибо Dwin за ответ! Это отлично работает для выборки с заменой. Но есть ли возможность сделать это без замены? Извините, что не ясно выразился в исходном вопросе... - person Lymond; 03.07.2012
comment
Я не понимаю. По умолчанию sample работает без_замены, таково текущее поведение. - person IRTFM; 03.07.2012
comment
Да. Но я хотел бы найти уникальные перестановки исходного вектора данных, разделенные на векторы размеров, заданных размерами. В вашем решении я получаю пять подвекторов, каждый из которых выбран без замены. Однако в векторах есть дубликаты. Я, вероятно, недостаточно опытен, чтобы адекватно сформулировать проблему с первого раза - я сожалею об этом! В любом случае, я думаю, что нашел разумное решение, также основанное на вашем ответе. (Смотри ниже) - person Lymond; 03.07.2012
comment
Ах, идеально. Большое спасибо за это предложение! :-) - person Lymond; 03.07.2012

Еще немного подумав и погуглив, я нашел приемлемое решение. Однако я до сих пор не уверен, что это самый быстрый и эффективный способ.

В принципе, я могу сгенерировать один длинный вектор уникальной перестановки «данных», а затем разделить его на список векторов длин «размеров», используя аргумент factor, предоставленный для разделения. Для этого мне нужна дополнительная схема идентификации для моих разных групп «данных», которая у меня есть в моем случае.

Это становится понятнее, если рассматривать его как код:

data <- list(c(1,5,6,3), c(2,4,7,8), c(9), c(10,11,15), c(12,13,14));
sizes <- lapply(data, length);

Пока все как выше

names <- c("set1", "set2", "set3", "set4", "set5");

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

names <- seq(1, length(data));

Затем этот вектор «имен» можно расширить на «размеры», используя rep:

cut.by <- rep(names, times = sizes);
[1] 1 1 1 1 2 2 2 2 3 4 4 4 5
[14] 5 5

Затем этот новый вектор "cut.by" может быть предоставлен в качестве аргумента функции split().

rand.data <- split(sample(1:15, 15), cut.by)
$`1`
[1]  8  9 14  4
$`2`
[1] 10  2 15 13
$`3`
[1] 12
$`4`
[1] 11  3  5
$`5`
[1] 7 6 1

Это делает работу, которую я искал, в порядке. Он производит выборку из фона "1:15" и разбивает результат на векторы длины "размеры" через вектор "cut.by".

Тем не менее, я все еще не доволен тем, что мне нужно пройти через дополнительный (возможно) длинный вектор, чтобы указать позиции разделения, такие как «cut.by» в приведенном выше коде. Это определенно работает, но я думаю, что для очень длинных векторов данных это может стать довольно медленным.

В любом случае спасибо за ответы и подсказки! Ваша помощь очень ценится :-)

person Lymond    schedule 03.07.2012