我有两个相关的用例,我需要总结一个表的部分,以类似的方式指定filter.
简而言之,我想要这样的东西:
iris %>%
use_only(Species == 'setosa') %>%
summarise_each(funs(sum), -Species) %>%
mutate(Species = 'setosa_sum') %>%
use_all()
Run Code Online (Sandbox Code Playgroud)
产生这个:
Source: local data frame [101 x 5]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 250.3 171.4 73.1 12.3 setosa_sum
2 7.0 3.2 4.7 1.4 versicolor
3 6.4 3.2 4.5 1.5 versicolor
4 6.9 3.1 4.9 1.5 versicolor
5 5.5 2.3 4.0 1.3 versicolor
…
Run Code Online (Sandbox Code Playgroud)
因此,我不使用列的值进行分组,而是使用过滤条件对表的视图进行操作,而不会实际丢失表的其余部分(与过滤器不同).
我如何巧妙地实施use_only/ use_all?更好的是,这个功能已经包含在内,dplyr我该如何使用它?
生成上面的结果当然很容易,但我需要为许多不同的情况做类似的事情,具有复杂和可变的过滤标准.
Dav*_*son 13
我use_only通过将表的其余部分保存到全局选项dplyr_use_only_rest并将use_all其重新绑定在一起的方法实现了这一点.
use_only <- function(.data, ...) {
if (!is.null(.data$.index)) {
stop("data cannot already have .index column, would be overwritten")
}
filt <- .data %>%
mutate(.index = row_number()) %>%
filter(...)
rest <- .data %>% slice(-filt$.index)
options(dplyr_use_only_rest = rest)
select(filt, -.index)
}
use_all <- function(.data, ...) {
rest <- getOption("dplyr_use_only_rest")
if (is.null(rest)) {
stop("called use_all() without earlier use_only()")
}
options(dplyr_use_only_rest = NULL)
bind_rows(.data, rest)
}
Run Code Online (Sandbox Code Playgroud)
我认识到设置全局选项并不是理想的函数式编程设计,但我认为还有另一种方法可以确保数据帧的其余部分不受任何中间函数的影响.向对象添加额外属性将无法使用诸如do或之类的函数summarize.
在此刻,
iris %>%
use_only(Species == 'setosa') %>%
summarise_each(funs(sum), -Species) %>%
mutate(Species = 'setosa_sum') %>%
use_all()
Run Code Online (Sandbox Code Playgroud)
根据需要返回:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 250.3 171.4 73.1 12.3 setosa_sum
2 7.0 3.2 4.7 1.4 versicolor
3 6.4 3.2 4.5 1.5 versicolor
4 6.9 3.1 4.9 1.5 versicolor
5 5.5 2.3 4.0 1.3 versicolor
...
Run Code Online (Sandbox Code Playgroud)
可以代替使用任何中间步骤summarize_each和mutate(do,filter,等),他们只会发生在指定的行.你甚至可以添加或删除列(其余部分将用NAs 填充).
edd*_*ddi 13
我认为您搜索函数以满足特定语法的方法过于严格.这就是我要做的事情data.table(我不确定是否dplyr允许这样的变量行,我知道它已经是FR了一段时间):
library(data.table)
dt = as.data.table(iris)
dt[, if (Species == 'setosa') lapply(.SD, sum) else .SD, by = Species]
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1: setosa 250.3 171.4 73.1 12.3
# 2: versicolor 7.0 3.2 4.7 1.4
# 3: versicolor 6.4 3.2 4.5 1.5
# 4: versicolor 6.9 3.1 4.9 1.5
# 5: versicolor 5.5 2.3 4.0 1.3
# ---
Run Code Online (Sandbox Code Playgroud)
您还可以[Species == 'setosa', Species := 'setosa_sum']在最后添加以修改名称.应该直接扩展到多个标准/任何功能.
您可以创建一个新列来分组:
iris %>%
mutate( group1 = ifelse(Species == "setosa", "", row_number())) %>%
group_by( group1, Species ) %>%
summarise_each(funs(sum), -Species, -group1) %>%
ungroup() %>%
select(-group1)
Run Code Online (Sandbox Code Playgroud)
library(lazyeval)
use_only_ <- function(x, condition, ...) {
condition <- as.lazy(condition, parent.frame())
mutate_(x, .group = condition) %>%
group_by_(".group", ...)
}
use_only <- function(x, condition, ...) {
use_only_(x, lazy(condition), ...)
}
use_all <- function(x) {
ungroup(x) %>%
select(- .group)
}
Run Code Online (Sandbox Code Playgroud)
use_only在数据框和调用环境的上下文中使用任何条件.在这种情况下:
iris %>%
use_only( ifelse(Species == "setosa", "", row_number()), "Species") %>%
summarise_each(funs(sum), -Species, -.group) %>%
use_all()
Run Code Online (Sandbox Code Playgroud)
的use_only_可与式或字符串来使用.例如:
condition <- ~ifelse(Species == "setosa", "", row_number())
Run Code Online (Sandbox Code Playgroud)
要么
condition <- "ifelse(Species == 'setosa' , "", row_number())"
Run Code Online (Sandbox Code Playgroud)
并致电:
iris %>%
use_only_(condition, "Species") %>%
summarise_each(funs(sum), -Species, -.group) %>%
use_all()
Run Code Online (Sandbox Code Playgroud)
在use_only和use_all调用之间进行变异时,必须注意仅更改标记组内的值.