在R数据框中,通过数据块长度生成随机数

4
我将尝试模拟测量顺序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"列,并根据每个块的长度生成随机整数。块在"A"列中定义。
结果应该类似于这样:
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的sample()函数生成随机数,但我的问题是根据块长度分割数据并添加新列。非常感谢任何帮助。


欢迎来到SO,很好地提供了可重现的示例。 - Richie Cotton
3个回答

4

使用ave可以轻松完成此操作。

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

你可以用max()或者其他函数替代length(),但是即使A不匹配块的长度,length()仍然可以正常工作。


ave()的功能演示非常好。真遗憾这样一个有用的函数有一个如此误导性的名称。即使是在?ave的文档中,也不能很好地传达它的真正作用。 - Josh O'Brien
是的,有点可惜...我猜他们最初使用的是平均值(average), 当你不指定“FUN”时,它就会这样工作。 - John
这也是一个很棒的解决方案!感谢您的帮助! - Markus Korhonen

2

使用plyr中的ddply非常简单。

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)

如果某个答案对您有帮助,请点击旁边的复选标记“接受”它,并表明您不再希望获得更多答案。 - Gregor Thomas
@shujaa 抱歉,我是新来的。谢谢你的提示。我已经标记了一个答案。 - Markus Korhonen
@MarkusKorhonen,别担心,欢迎来到这个网站!正如Richie已经评论的那样,很好地提出了一个高质量的第一个问题。 - Gregor Thomas

1

一种简单的方法:

df$D = 0

counts = table(df$A)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接