Генерация случайного числа по длине блоков данных в кадре данных R - PullRequest
4 голосов
/ 06 января 2012

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

Пример данных (каждая строка является наблюдением):

df <- data.frame(A=c(1,1,1,2,2,3,3,3,3), 
                 B=c("x","b","c","g","h","g","g","u","l"), 
                 C=c(1,2,4,1,5,7,1,2,5))


  A B C
1 1 x 1
2 1 b 2
3 1 c 4
4 2 g 1
5 2 h 5
6 3 g 7
7 3 g 1
8 3 u 2
9 3 l 5

Что я хотел бы сделать, это добавить столбец D и генерировать случайные целые числа в соответствии с длиной каждого блока. Блоки определены в столбце А.

Результат должен выглядеть примерно так:

df <- data.frame(A=c(1,1,1,2,2,3,3,3,3), 
                 B=c("x","b","c","g","h","g","g","u","l"), 
                 C=c(1,2,4,1,5,7,1,2,5),
                 D=c(2,1,3,2,1,4,3,1,2))

> df
  A B C D
1 1 x 1 2
2 1 b 2 1
3 1 c 4 3
4 2 g 1 2
5 2 h 5 1
6 3 g 7 4
7 3 g 1 3
8 3 u 2 1
9 3 l 5 2

Я пытался использовать функцию R: s sample() для генерации случайных чисел, но моя проблема - разбить данные по длине блока и добавить новый столбец. Любая помощь с благодарностью.

Ответы [ 3 ]

4 голосов
/ 06 января 2012

Это легко сделать с помощью ave

df$D <- ave( df$A, df$A, FUN = function(x) sample(length(x)) )

(вы могли бы заменить length () на max () или как угодно, но длина будет работать, даже если A не является числом, соответствующим длине их блоков)

2 голосов
/ 06 января 2012

Это действительно легко с ddply из plyr.

ddply(df, .(A), transform, D = sample(length(A)))

Более длинная версия вручную:

Используйте split, чтобы разделить фрейм данных по первому столбцу.

split_df <- split(df, df$A)

Затем вызовите sample для каждого члена списка.

split_df <- lapply(split_df, function(df) 
{
  df$D <- sample(nrow(df))
  df
})

Затем рекомбинируйте с

df <- do.call(rbind, split_df)
1 голос
/ 06 января 2012

Один простой способ:

df$D = 0

counts = table(df$A)

for (i in 1:length(counts)){
    df$D[df$A == names(counts)[i]] = sample(counts[i])
}
...