【问题标题】:dplyr: Integer sampling within mutatedplyr:突变内的整数采样
【发布时间】:2015-05-01 09:22:28
【问题描述】:

我正在尝试在 tbl_df 中生成一列,它是 0 或 1 的随机整数。这是我正在使用的代码:

library(dplyr)
set.seed(0)

#Dummy data.frame to test
df <- tbl_df(data.frame(x = rep(1:3, each = 4)))

#Generate the random integer column
df_test = df %>% 
  mutate(pop=sample(0:1, 1, replace=TRUE))

但这似乎不像我预期的那样工作。我生成的字段似乎全为零。这是因为mutate 中的语句是并行评估的,因此最终使用相同的种子进行第一次随机抽取?

df_test 
Source: local data frame [12 x 2]

   x pop
1  1   0
2  1   0
3  1   0
4  1   0
5  2   0
6  2   0
7  2   0
8  2   0
9  3   0
10 3   0
11 3   0
12 3   0

在过去的几个小时里,我对此感到头疼。知道我的脚本有什么缺陷吗?

【问题讨论】:

  • 使用sample(0:1, 12, replace=TRUE)
  • 或sample(0:1, n(), replace = TRUE)

标签: r dplyr


【解决方案1】:

按照您的代码编写方式,您正在为整个向量分配一个值(随机抽取的结果)(这称为“向量回收”)。

在这种情况下,最好的解决方案是 Steven Beaupré 的回答,即创建一个与 data.frame 长度相同的随机向量:

df %>% 
  mutate(pop = sample(0:1, n(), replace = TRUE))

一般来说,如果您想在 dplyr 中逐行应用一个函数 - 正如您所想的那样 - 您可以使用 rowwise(),尽管在此示例中它不是必需的。

这是rowwise() 的示例:

df2 <- data.frame(a = c(1,3,6), b = c(2,4,5))

df2 %>%
  mutate(m = max(a,b))

  a b m
1 1 2 6
2 3 4 6
3 6 5 6

df2 %>%
  rowwise() %>%
  mutate(m = max(a,b))

  a b m
1 1 2 2
2 3 4 4
3 6 5 6

由于rowwise 对每行操作的数据进行分组,因此可能比没有任何分组的情况要慢。因此,最好尽可能使用向量化函数,而不是逐行操作。


基准测试:

rowwise() 的方法慢了大约 30 倍:

library(microbenchmark)
df <- tbl_df(data.frame(x = rep(1:1000, each = 4)))
bench <- microbenchmark(
  vectorized = df2 <- df %>% mutate(pop = sample(0:1, n(), replace = TRUE)),
  rowwise = df2 <- df %>% rowwise() %>% mutate(pop = sample(0:1, 1, replace = TRUE)),
  times = 1000
  )

options(microbenchmark.unit="relative")
print(bench)
autoplot(bench)

Unit: relative
       expr      min       lq     mean   median       uq     max neval
 vectorized  1.00000  1.00000  1.00000  1.00000  1.00000  1.0000  1000
    rowwise 42.53169 42.29486 36.94876 33.70456 34.92621 71.7682  1000

【讨论】:

  • 这很好用。那么mutate 中的表达式在没有此运算符的情况下不会针对每一行进行评估?所以有某种形式的 numpy,比如 mutate 发生的广播?
  • 没错。我添加了一个更典型的 rowwise() 应用示例。
  • rowwise 在这种情况下不是必需的。相反,我认为史蒂文对这个问题的评论中的方法是最好的。
  • @docendodiscimus 我同意,我也会用 Steven 的方法解决这个问题。但我认为解释mutate 如何以这种方式工作是有好处的。我会看看他是否会发布他的评论作为我们可以投票的答案,否则我会将其变成社区 wiki 并纳入他的方法。
  • 两种方法之间的性能差异非常大;我在答案中添加了基准测试结果。
猜你喜欢
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
相关资源
最近更新 更多