dplyr:突变内的整数采样
dplyr: Integer sampling within mutate
我正在尝试在 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
在过去的几个小时里,我为此伤透了脑筋。知道我的脚本有什么缺陷吗?
按照您编写代码的方式,您是将单个值(随机抽取的结果)分配给整个向量(这称为 "vector recycling")。
在这种情况下最好的解决方案是 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
我正在尝试在 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
在过去的几个小时里,我为此伤透了脑筋。知道我的脚本有什么缺陷吗?
按照您编写代码的方式,您是将单个值(随机抽取的结果)分配给整个向量(这称为 "vector recycling")。
在这种情况下最好的解决方案是 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