在R数据帧中生成随机数,这些数字在相似行中是恒定的

ant*_*thr 2 r dataframe split-apply-combine

我有一个数据帧,每个'用户'包含X行,其中X在用户之间不是常数.我想要做的是能够生成随机数来填充新列,但对于每个"用户",随机数在与该用户对应的所有行中是相同的.例如,数据可能如下所示:

user    feature1     feature2
 1        "A"           "B"
 1        "L"           "L"
 1        "Q"           "B"
 1        "D"           "M"
 1        "D"           "M"
 1        "P"           "E"
 2        "A"           "B"
 2        "R"           "P"
 2        "A"           "F"
 3        "X"           "U"
...       ...           ...
Run Code Online (Sandbox Code Playgroud)

我想生成一个新列,可能看起来像这样:

user    feature1     feature2   new_rand
 1        "A"           "B"       0.183
 1        "L"           "L"       0.183
 1        "Q"           "B"       0.183
 1        "D"           "M"       0.183
 1        "D"           "M"       0.183
 1        "P"           "E"       0.183
 2        "A"           "B"       0.971
 2        "R"           "P"       0.971
 2        "A"           "F"       0.971
 3        "X"           "U"       0.302
...       ...           ...
Run Code Online (Sandbox Code Playgroud)

我做的第一种方法是基本使用,s <- split(df, df$user)但数据框包含大量用户,我认为这可能是一种非常低效的方法.

非常感谢.

Mic*_*ico 6

@ akrun的方法是一个伟大的一次性但它不利用矢量化(我们rnorm在每个级别内反复调用一次user),所以它可能在缓慢的一面.更通用的方法是:

library(data.table)
setDT(df)
df[unique(df, by = "user")[ , new_rand := rnorm(.N)],
   new_rand := i.new_rand, on = "user"]
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?unique返回一个新的data.table,所有的重复的观测(如由下式定义by,这里user)被去除; 然后我们在这个新对象([, := ])中添加一列.最后,这个扩充data.table连接回原始表.

请注意,这里我们只调用rnorm一次,返回一个大小合适的矢量.然后我们将其连接回原始数据集,根据需要在每个观察值中"扩展"该值user.

或分配到更具体的群体,说userfeature1feature2:

grps <- c("user", "feature1", "feature2")
df[unique(df, by = grps)[ , new_rand := rnorm(.N)],
   new_rand := i.new_rand, on = grps]
Run Code Online (Sandbox Code Playgroud)