我有一个数据框,每个用户都有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"
... ... ...
我希望生成一个可能如下所示的新列:
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
... ... ...
我做的第一种方法是基本上使用s <- split(df, df$user)
,但数据框包含大量用户,我认为这可能是一种非常低效的方法。
非常感谢。
答案 0 :(得分: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"]
这里发生了什么? unique
会返回一个新的data.table
,其中删除了所有重复的观察结果(由by
定义,此处为user
);然后我们为这个新对象添加一列([, := ]
)。最后,这个增强的data.table
将重新连接到原始表格。
请注意,这里我们只调用rnorm
一次,返回一个大小合适的矢量。然后,我们将其加入到原始数据集中,根据需要在每个user
的所有观察值中“传播”该值。
或者,如果要分配给更具体的群组,请说user
和feature1
以及feature2
:
grps <- c("user", "feature1", "feature2")
df[unique(df, by = grps)[ , new_rand := rnorm(.N)],
new_rand := i.new_rand, on = grps]
答案 1 :(得分:3)
我们可以尝试data.table
。我们转换了&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df1)
),按&#39;用户&#39;分组,我们得到一个随机数(rnorm(1)
)并指定(:=
)来创建&#39; new_rand&#39 ;
library(data.table)
setDT(df1)[, new_rand := rnorm(1) , by = user]
或者我们可以使用dplyr
。
library(dplyr)
df1 %>%
group_by(user) %>%
mutate(new_rand = rnorm(1))
或left_join
distinct(df1, user) %>%
mutate(new_rand=rnorm(n())) %>%
left_join(df1, ., by='user')
答案 2 :(得分:3)
和基础R解决方案:
df_ <- data.frame(user = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 3), feature1 = c("A", "L", "Q", "D", "D", "P", "A", "R", "A", "X"), feature2 = c("B", "L", "B", "M", "M", "E", "B", "P", "F", "U"))
tmp <- by(df_, df_[, 'user'], FUN = function(x) data.frame(x, new_rand = rnorm(1)))
do.call(rbind, tmp)
# user feature1 feature2 new_rand
# 1.1 1 A B -0.6145338
# 1.2 1 L L -0.6145338
# 1.3 1 Q B -0.6145338
# 1.4 1 D M -0.6145338
# 1.5 1 D M -0.6145338
# 1.6 1 P E -0.6145338
# 2.7 2 A B -1.4292151
# 2.8 2 R P -1.4292151
# 2.9 2 A F -1.4292151
# 3 3 X U -0.3309754
或根据akrun的建议:
df_[, 'new_rand'] <- ave(seq_along(df_$user), df_$user, FUN = function(x) rnorm(1))