调整函数以使用 dplyr/magrittr
Adjust function to work with dplyr/magrittr
我有:
df <- data_frame(
a = 1:2,
b = list(1:10, 4:40)
)
和
foo <- function(x) mean(unlist(x))
以下按预期工作:
df$b %>% foo
但是,我无法弄清楚需要对 foo
进行哪些修改才能使 df %>% foo(b)
正常工作。
您可以这样得到结果:
library(dplyr)
library(purrr)
df %>%
mutate_(mn=~map_dbl(b, mean), size=~map_dbl(b, length)) %>%
summarize_(m=~weighted.mean(mn, size))
# m
# <dbl>
# 1 18.49
或者这样定义foo
:
foo2 <- function(d, col) {
col_name <- as.character(substitute(col))
mean(unlist(d[[col_name]]))
}
df %>% foo2(b)
[1] 18.49
您可以将 ...
参数直接传递给 summarise_at
的 vars
助手,例如
foo <- function(.tbl, ...){
summarise_at(.tbl,
vars(...),
funs(mean(unlist(.))))
}
它适用于单个变量,列表列或不:
df %>% foo(b)
## # A tibble: 1 × 1
## b
## <dbl>
## 1 18.48936
或多个:
df %>% foo(a, b)
## # A tibble: 1 × 2
## a b
## <dbl> <dbl>
## 1 1.5 18.48936
要进一步了解 NSE,请查看 lazyeval,这是 dplyr 用来实现其 NSE 的包。
另请注意,dplyr 的 SE/NSE 系统刚刚在开发版本中重建(尚未在 CRAN 上,尚未记录)。
奖励积分:全部以 R 为基数完成!
foo <- function(.tbl, ...){
# collect dots as character vector
cols <- as.character(substitute(list(...))[-1])
cls <- class(.tbl)
# handle grouped tibbles properly
if('grouped_df' %in% cls){
cls <- cls[which(cls != 'grouped_df')] # drop grouping
res <- aggregate(.tbl[cols],
.tbl[attr(.tbl, 'vars')],
FUN = function(x){mean(unlist(x))})
} else {
res <- as.data.frame(lapply(.tbl[cols], function(x){mean(unlist(x))}))
}
class(res) <- cls # keep class (tibble, etc.)
res
}
适用于列表列、组和多个列或组,保留 class 但删除分组:
df %>% foo(a, b)
## # A tibble: 1 × 2
## a b
## <dbl> <dbl>
## 1 1.5 18.48936
df %>% group_by(a) %>% foo(b)
## # A tibble: 2 × 2
## a b
## <int> <dbl>
## 1 1 5.5
## 2 2 22.0
mtcars %>% foo(mpg, hp)
## mpg hp
## 1 20.09062 146.6875
mtcars %>% group_by(cyl, am) %>% foo(hp, mpg)
## # A tibble: 6 × 4
## cyl am hp mpg
## <dbl> <dbl> <dbl> <dbl>
## 1 4 0 84.66667 22.90000
## 2 6 0 115.25000 19.12500
## 3 8 0 194.16667 15.05000
## 4 4 1 81.87500 28.07500
## 5 6 1 131.66667 20.56667
## 6 8 1 299.50000 15.40000
您可以使用以下内容更新函数:
foo <- function(df, x) {
x <- df[ deparse(substitute(x))]
mean(unlist(x)) }
df %>% foo(b)
[1] 18.48936
我有:
df <- data_frame(
a = 1:2,
b = list(1:10, 4:40)
)
和
foo <- function(x) mean(unlist(x))
以下按预期工作:
df$b %>% foo
但是,我无法弄清楚需要对 foo
进行哪些修改才能使 df %>% foo(b)
正常工作。
您可以这样得到结果:
library(dplyr)
library(purrr)
df %>%
mutate_(mn=~map_dbl(b, mean), size=~map_dbl(b, length)) %>%
summarize_(m=~weighted.mean(mn, size))
# m
# <dbl>
# 1 18.49
或者这样定义foo
:
foo2 <- function(d, col) {
col_name <- as.character(substitute(col))
mean(unlist(d[[col_name]]))
}
df %>% foo2(b)
[1] 18.49
您可以将 ...
参数直接传递给 summarise_at
的 vars
助手,例如
foo <- function(.tbl, ...){
summarise_at(.tbl,
vars(...),
funs(mean(unlist(.))))
}
它适用于单个变量,列表列或不:
df %>% foo(b)
## # A tibble: 1 × 1
## b
## <dbl>
## 1 18.48936
或多个:
df %>% foo(a, b)
## # A tibble: 1 × 2
## a b
## <dbl> <dbl>
## 1 1.5 18.48936
要进一步了解 NSE,请查看 lazyeval,这是 dplyr 用来实现其 NSE 的包。
另请注意,dplyr 的 SE/NSE 系统刚刚在开发版本中重建(尚未在 CRAN 上,尚未记录)。
奖励积分:全部以 R 为基数完成!
foo <- function(.tbl, ...){
# collect dots as character vector
cols <- as.character(substitute(list(...))[-1])
cls <- class(.tbl)
# handle grouped tibbles properly
if('grouped_df' %in% cls){
cls <- cls[which(cls != 'grouped_df')] # drop grouping
res <- aggregate(.tbl[cols],
.tbl[attr(.tbl, 'vars')],
FUN = function(x){mean(unlist(x))})
} else {
res <- as.data.frame(lapply(.tbl[cols], function(x){mean(unlist(x))}))
}
class(res) <- cls # keep class (tibble, etc.)
res
}
适用于列表列、组和多个列或组,保留 class 但删除分组:
df %>% foo(a, b)
## # A tibble: 1 × 2
## a b
## <dbl> <dbl>
## 1 1.5 18.48936
df %>% group_by(a) %>% foo(b)
## # A tibble: 2 × 2
## a b
## <int> <dbl>
## 1 1 5.5
## 2 2 22.0
mtcars %>% foo(mpg, hp)
## mpg hp
## 1 20.09062 146.6875
mtcars %>% group_by(cyl, am) %>% foo(hp, mpg)
## # A tibble: 6 × 4
## cyl am hp mpg
## <dbl> <dbl> <dbl> <dbl>
## 1 4 0 84.66667 22.90000
## 2 6 0 115.25000 19.12500
## 3 8 0 194.16667 15.05000
## 4 4 1 81.87500 28.07500
## 5 6 1 131.66667 20.56667
## 6 8 1 299.50000 15.40000
您可以使用以下内容更新函数:
foo <- function(df, x) {
x <- df[ deparse(substitute(x))]
mean(unlist(x)) }
df %>% foo(b)
[1] 18.48936