在函数中使用 dplyr,非标准评估
Using dplyr within a function, non-standard evaluation
试图让我的头脑Non-Standard Evaluation as used by dplyr但没有成功。我想要一个简短的函数,它 returns 一组指定变量的汇总统计数据(N、平均值、标准差、中位数、IQR、最小值、最大值)。
我的函数的简化版本...
my_summarise <- function(df = temp,
to.sum = 'eg1',
...){
## Summarise
results <- summarise_(df,
n = ~n(),
mean = mean(~to.sum, na.rm = TRUE))
return(results)
}
并且 运行 它带有一些虚拟数据...
set.seed(43290)
temp <- cbind(rnorm(n = 100, mean = 2, sd = 4),
rnorm(n = 100, mean = 3, sd = 6)) %>% as.data.frame()
names(temp) <- c('eg1', 'eg2')
mean(temp$eg1)
[1] 1.881721
mean(temp$eg2)
[1] 3.575819
my_summarise(df = temp, to.sum = 'eg1')
n mean
1 100 NA
N算出来了,但不是均值,想不通为什么。
最终我希望我的函数更通用,按照...
my_summarise <- function(df = temp,
group.by = 'group'
to.sum = c('eg1', 'eg2'),
...){
results <- list()
## Select columns
df <- dplyr::select_(df, .dots = c(group.by, to.sum))
## Summarise overall
results$all <- summarise_each(df,
funs(n = ~n(),
mean = mean(~to.sum, na.rm = TRUE)))
## Summarise by specified group
results$by.group <- group_by_(df, ~to.group) %>%
summarise_each(df,
funs(n = ~n(),
mean = mean(~to.sum, na.rm = TRUE)))
return(results)
}
...但在我进入这个更复杂的版本(我使用 this example 作为指导)之前,我需要先在简单版本中进行评估,因为那是绊脚石,调用到 dplyr::select()
工作正常。
感谢任何关于我哪里出错的建议。
提前致谢
基本思想是您必须自己实际构建适当的调用,使用 lazyeval
包最容易完成。
在这种情况下,您希望以编程方式创建一个类似于 ~mean(eg1, na.rm = TRUE)
的调用。是这样的:
my_summarise <- function(df = temp,
to.sum = 'eg1',
...){
## Summarise
results <- summarise_(df,
n = ~n(),
mean = lazyeval::interp(~mean(x, na.rm = TRUE),
x = as.name(to.sum)))
return(results)
}
以下是我在努力使事情正常运行时所做的事情:
- 请记住,就像您已有的
~n()
一样,调用必须以 ~
开头。
- 用实际变量编写正确的调用,看看它是否有效 (
~mean(eg1, na.rm = TRUE)
)。
- 使用
lazyeval::interp
重新创建该调用,并仅通过 运行 检查 interp
以直观地查看它在做什么。
在这种情况下我可能会经常写interp(~mean(x, na.rm = TRUE), x = to.sum)
。但是 运行 会给我们 ~mean("eg1", na.rm = TRUE)
,它把 eg1
当作字符而不是变量名。所以我们使用 as.name
,正如 vignette("nse")
.
中教给我们的那样
试图让我的头脑Non-Standard Evaluation as used by dplyr但没有成功。我想要一个简短的函数,它 returns 一组指定变量的汇总统计数据(N、平均值、标准差、中位数、IQR、最小值、最大值)。
我的函数的简化版本...
my_summarise <- function(df = temp,
to.sum = 'eg1',
...){
## Summarise
results <- summarise_(df,
n = ~n(),
mean = mean(~to.sum, na.rm = TRUE))
return(results)
}
并且 运行 它带有一些虚拟数据...
set.seed(43290)
temp <- cbind(rnorm(n = 100, mean = 2, sd = 4),
rnorm(n = 100, mean = 3, sd = 6)) %>% as.data.frame()
names(temp) <- c('eg1', 'eg2')
mean(temp$eg1)
[1] 1.881721
mean(temp$eg2)
[1] 3.575819
my_summarise(df = temp, to.sum = 'eg1')
n mean
1 100 NA
N算出来了,但不是均值,想不通为什么。
最终我希望我的函数更通用,按照...
my_summarise <- function(df = temp,
group.by = 'group'
to.sum = c('eg1', 'eg2'),
...){
results <- list()
## Select columns
df <- dplyr::select_(df, .dots = c(group.by, to.sum))
## Summarise overall
results$all <- summarise_each(df,
funs(n = ~n(),
mean = mean(~to.sum, na.rm = TRUE)))
## Summarise by specified group
results$by.group <- group_by_(df, ~to.group) %>%
summarise_each(df,
funs(n = ~n(),
mean = mean(~to.sum, na.rm = TRUE)))
return(results)
}
...但在我进入这个更复杂的版本(我使用 this example 作为指导)之前,我需要先在简单版本中进行评估,因为那是绊脚石,调用到 dplyr::select()
工作正常。
感谢任何关于我哪里出错的建议。
提前致谢
基本思想是您必须自己实际构建适当的调用,使用 lazyeval
包最容易完成。
在这种情况下,您希望以编程方式创建一个类似于 ~mean(eg1, na.rm = TRUE)
的调用。是这样的:
my_summarise <- function(df = temp,
to.sum = 'eg1',
...){
## Summarise
results <- summarise_(df,
n = ~n(),
mean = lazyeval::interp(~mean(x, na.rm = TRUE),
x = as.name(to.sum)))
return(results)
}
以下是我在努力使事情正常运行时所做的事情:
- 请记住,就像您已有的
~n()
一样,调用必须以~
开头。 - 用实际变量编写正确的调用,看看它是否有效 (
~mean(eg1, na.rm = TRUE)
)。 - 使用
lazyeval::interp
重新创建该调用,并仅通过 运行 检查interp
以直观地查看它在做什么。
在这种情况下我可能会经常写interp(~mean(x, na.rm = TRUE), x = to.sum)
。但是 运行 会给我们 ~mean("eg1", na.rm = TRUE)
,它把 eg1
当作字符而不是变量名。所以我们使用 as.name
,正如 vignette("nse")
.