为什么我使用 SE 或 NSE dplyr 函数得到不同的结果
Why do i got different results using SE or NSE dplyr functions
嗨,当我通过 lazyeval 包使用标准评估时,我从 dplyr 函数得到了不同的结果。
这里是如何使用 250k 行和大约 230k 组重现接近我的真实数据的东西。我想按 id1、id2 分组,并为每个组使用 max(datetime) 对行进行子集化。
library(dplyr)
# random datetime generation function by Dirk Eddelbuettel
#
rand.datetime <- function(N, st = "2012/01/01", et = "2015/08/13") {
st <- as.POSIXct(as.Date(st))
et <- as.POSIXct(as.Date(et))
dt <- as.numeric(difftime(et,st,unit="sec"))
ev <- sort(runif(N, 0, dt))
rt <- st + ev
}
set.seed(42)
# Creating 230000 ids couples
ids <- data_frame(id1 = stringi::stri_rand_strings(23e4, 9, pattern = "[0-9]"),
id2 = stringi::stri_rand_strings(23e4, 9, pattern = "[0-9]"))
# Repeating randomly the ids[1:2000, ] to create groups
ids <- rbind(ids, ids[sample(1:2000, 20000, replace = TRUE), ])
datas <- mutate(ids, datetime = rand.datetime(25e4))
当我使用 NSE 方式时,我得到了 230000 行
df1 <-
datas %>%
group_by(id1, id2) %>%
filter(datetime == max(datetime))
nrow(df1) #230000
但是当我使用 SE 时,我只有 229977 行
ids <- c("id1", "id2")
filterVar <- "datetime"
filterFun <- "max"
df2 <-
datas %>%
group_by_(ids) %>%
filter_(.dots = lazyeval::interp(~var == fun(var),
var = as.name(filterVar),
fun = as.name(filterFun)))
nrow(df2) #229977
我的两段代码是等价的吧?
为什么我会遇到不同的结果?谢谢
在给出列名向量时,您需要在 group_by_
中指定 .dots
参数。
df2 <- datas %>%
group_by_(.dots = ids) %>%
filter_(.dots = lazyeval::interp(~var == fun(var),
var = as.name(filterVar),
fun = as.name(filterFun)))
nrow(df2)
[1] 230000
当您未指定 .dots
参数时,group_by_
可能会将向量中的第一列名称作为唯一的分组变量。您可以通过仅在 id1
上分组来检查。
df1 <- datas %>%
group_by(id1) %>%
filter(datetime == max(datetime))
nrow(df1)
[1] 229977
(如果仅在 id2
上分组,行数为 229976)。
嗨,当我通过 lazyeval 包使用标准评估时,我从 dplyr 函数得到了不同的结果。
这里是如何使用 250k 行和大约 230k 组重现接近我的真实数据的东西。我想按 id1、id2 分组,并为每个组使用 max(datetime) 对行进行子集化。
library(dplyr)
# random datetime generation function by Dirk Eddelbuettel
#
rand.datetime <- function(N, st = "2012/01/01", et = "2015/08/13") {
st <- as.POSIXct(as.Date(st))
et <- as.POSIXct(as.Date(et))
dt <- as.numeric(difftime(et,st,unit="sec"))
ev <- sort(runif(N, 0, dt))
rt <- st + ev
}
set.seed(42)
# Creating 230000 ids couples
ids <- data_frame(id1 = stringi::stri_rand_strings(23e4, 9, pattern = "[0-9]"),
id2 = stringi::stri_rand_strings(23e4, 9, pattern = "[0-9]"))
# Repeating randomly the ids[1:2000, ] to create groups
ids <- rbind(ids, ids[sample(1:2000, 20000, replace = TRUE), ])
datas <- mutate(ids, datetime = rand.datetime(25e4))
当我使用 NSE 方式时,我得到了 230000 行
df1 <-
datas %>%
group_by(id1, id2) %>%
filter(datetime == max(datetime))
nrow(df1) #230000
但是当我使用 SE 时,我只有 229977 行
ids <- c("id1", "id2")
filterVar <- "datetime"
filterFun <- "max"
df2 <-
datas %>%
group_by_(ids) %>%
filter_(.dots = lazyeval::interp(~var == fun(var),
var = as.name(filterVar),
fun = as.name(filterFun)))
nrow(df2) #229977
我的两段代码是等价的吧? 为什么我会遇到不同的结果?谢谢
在给出列名向量时,您需要在 group_by_
中指定 .dots
参数。
df2 <- datas %>%
group_by_(.dots = ids) %>%
filter_(.dots = lazyeval::interp(~var == fun(var),
var = as.name(filterVar),
fun = as.name(filterFun)))
nrow(df2)
[1] 230000
当您未指定 .dots
参数时,group_by_
可能会将向量中的第一列名称作为唯一的分组变量。您可以通过仅在 id1
上分组来检查。
df1 <- datas %>%
group_by(id1) %>%
filter(datetime == max(datetime))
nrow(df1)
[1] 229977
(如果仅在 id2
上分组,行数为 229976)。