单步执行具有中间结果的管道
Stepping through a pipeline with intermediate results
有没有办法不用手动输出每一步流水线的结果? (例如,没有 selecting 和 运行ning 只有 selected 块)
我经常发现自己 运行逐行运行管道以记住它在做什么或何时进行某些分析。
例如:
library(dplyr)
mtcars %>%
group_by(cyl) %>%
sample_frac(0.1) %>%
summarise(res = mean(mpg))
# Source: local data frame [3 x 2]
#
# cyl res
# 1 4 33.9
# 2 6 18.1
# 3 8 18.7
我会 select 和 运行:
mtcars %>% group_by(cyl)
然后...
mtcars %>% group_by(cyl) %>% sample_frac(0.1)
等等...
但是 selecting 和 CMD/CTRL
+ENTER
在 RStudio
中留下了更有效的方法。
这可以用代码完成吗?
是否有一个函数需要一个管道,runs/digests 它逐行显示控制台中每一步的输出,然后您可以像 demos(...)
中那样按回车键继续examples(...)
个包指南
添加打印:
mtcars %>%
group_by(cyl) %>%
print %>%
sample_frac(0.1) %>%
print %>%
summarise(res = mean(mpg))
使用 magrittr 函数链很容易。例如定义一个函数 my_chain
with:
foo <- function(x) x + 1
bar <- function(x) x + 1
baz <- function(x) x + 1
my_chain <- . %>% foo %>% bar %>% baz
并得到链的最终结果为:
> my_chain(0)
[1] 3
您可以通过 functions(my_chain)
获取函数列表
并像这样定义一个 "stepper" 函数:
stepper <- function(fun_chain, x, FUN = print) {
f_list <- functions(fun_chain)
for(i in seq_along(f_list)) {
x <- f_list[[i]](x)
FUN(x)
}
invisible(x)
}
和运行插入print
函数的链:
stepper(my_chain, 0, print)
# [1] 1
# [1] 2
# [1] 3
或者等待用户输入:
stepper(my_chain, 0, function(x) {print(x); readline()})
恕我直言,magrittr 主要用于交互,即当我探索数据或构建新的 formula/model。
在这种情况下,将中间结果存储在不同的变量中非常耗时且分散注意力,而管道让我专注于数据,而不是输入:
x %>% foo
## reason on results and
x %>% foo %>% bar
## reason on results and
x %>% foo %>% bar %>% baz
## etc.
这里的问题是我事先不知道最终的管道是什么,就像@bergant 一样。
打字,如@zx8754,
x %>% print %>% foo %>% print %>% bar %>% print %>% baz
增加了很多开销,对我来说,破坏了 magrittr 的全部目的。
本质上 magrittr 缺少一个简单的运算符,prints 和 pipes 结果。
好消息是制作一个似乎很容易:
`%P>%`=function(lhs, rhs){ print(lhs); lhs %>% rhs }
现在您可以打印管道了:
1:4 %P>% sqrt %P>% sum
## [1] 1 2 3 4
## [1] 1.000000 1.414214 1.732051 2.000000
## [1] 6.146264
我发现如果一个 defines/uses %P>%
和 %>%
的键绑定,原型制作工作流程非常精简(参见 Emacs ESS or RStudio)。
您可以 select 使用发球运算符 (%T>%
) 和 print()
打印哪些结果。 tee-operator 专门用于打印等副作用。
# i.e.
mtcars %>%
group_by(cyl) %T>% print() %>%
sample_frac(0.1) %T>% print() %>%
summarise(res = mean(mpg))
我编写了包 pipes,它可以做几件可能有帮助的事情:
- 使用
%P>%
到 print
输出。
- 使用
%ae>%
在输入和输出上使用 all.equal
。
- 使用
%V>%
在输出上使用 View
,它将为每个相关步骤打开一个查看器。
如果您想查看一些汇总信息,您可以尝试 %summary>%
、%glimpse>%
或 %skim>%
,这将使用 summary
、tibble::glimpse
或 skimr::skim
,或者您可以使用 new_pipe
定义自己的管道以显示特定的更改
# devtools::install_github("moodymudskipper/pipes")
library(dplyr)
library(pipes)
res <- mtcars %P>%
group_by(cyl) %P>%
sample_frac(0.1) %P>%
summarise(res = mean(mpg))
#> group_by(., cyl)
#> # A tibble: 32 x 11
#> # Groups: cyl [3]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
#> 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
#> 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
#> 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
#> 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
#> 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
#> 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
#> 8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
#> 9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
#> 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
#> # ... with 22 more rows
#> sample_frac(., 0.1)
#> # A tibble: 3 x 11
#> # Groups: cyl [3]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 26 4 120. 91 4.43 2.14 16.7 0 1 5 2
#> 2 17.8 6 168. 123 3.92 3.44 18.9 1 0 4 4
#> 3 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
#> summarise(., res = mean(mpg))
#> # A tibble: 3 x 2
#> cyl res
#> <dbl> <dbl>
#> 1 4 26
#> 2 6 17.8
#> 3 8 18.7
res <- mtcars %ae>%
group_by(cyl) %ae>%
sample_frac(0.1) %ae>%
summarise(res = mean(mpg))
#> group_by(., cyl)
#> [1] "Attributes: < Names: 1 string mismatch >"
#> [2] "Attributes: < Length mismatch: comparison on first 2 components >"
#> [3] "Attributes: < Component \"class\": Lengths (1, 4) differ (string compare on first 1) >"
#> [4] "Attributes: < Component \"class\": 1 string mismatch >"
#> [5] "Attributes: < Component 2: Modes: character, list >"
#> [6] "Attributes: < Component 2: Lengths: 32, 2 >"
#> [7] "Attributes: < Component 2: names for current but not for target >"
#> [8] "Attributes: < Component 2: Attributes: < target is NULL, current is list > >"
#> [9] "Attributes: < Component 2: target is character, current is tbl_df >"
#> sample_frac(., 0.1)
#> [1] "Different number of rows"
#> summarise(., res = mean(mpg))
#> [1] "Cols in y but not x: `res`. "
#> [2] "Cols in x but not y: `qsec`, `wt`, `drat`, `hp`, `disp`, `mpg`, `carb`, `gear`, `am`, `vs`. "
res <- mtcars %V>%
group_by(cyl) %V>%
sample_frac(0.1) %V>%
summarise(res = mean(mpg))
# you'll have to test this one by yourself
有没有办法不用手动输出每一步流水线的结果? (例如,没有 selecting 和 运行ning 只有 selected 块)
我经常发现自己 运行逐行运行管道以记住它在做什么或何时进行某些分析。
例如:
library(dplyr)
mtcars %>%
group_by(cyl) %>%
sample_frac(0.1) %>%
summarise(res = mean(mpg))
# Source: local data frame [3 x 2]
#
# cyl res
# 1 4 33.9
# 2 6 18.1
# 3 8 18.7
我会 select 和 运行:
mtcars %>% group_by(cyl)
然后...
mtcars %>% group_by(cyl) %>% sample_frac(0.1)
等等...
但是 selecting 和 CMD/CTRL
+ENTER
在 RStudio
中留下了更有效的方法。
这可以用代码完成吗?
是否有一个函数需要一个管道,runs/digests 它逐行显示控制台中每一步的输出,然后您可以像 demos(...)
中那样按回车键继续examples(...)
个包指南
添加打印:
mtcars %>%
group_by(cyl) %>%
print %>%
sample_frac(0.1) %>%
print %>%
summarise(res = mean(mpg))
使用 magrittr 函数链很容易。例如定义一个函数 my_chain
with:
foo <- function(x) x + 1
bar <- function(x) x + 1
baz <- function(x) x + 1
my_chain <- . %>% foo %>% bar %>% baz
并得到链的最终结果为:
> my_chain(0)
[1] 3
您可以通过 functions(my_chain)
获取函数列表
并像这样定义一个 "stepper" 函数:
stepper <- function(fun_chain, x, FUN = print) {
f_list <- functions(fun_chain)
for(i in seq_along(f_list)) {
x <- f_list[[i]](x)
FUN(x)
}
invisible(x)
}
和运行插入print
函数的链:
stepper(my_chain, 0, print)
# [1] 1
# [1] 2
# [1] 3
或者等待用户输入:
stepper(my_chain, 0, function(x) {print(x); readline()})
恕我直言,magrittr 主要用于交互,即当我探索数据或构建新的 formula/model。
在这种情况下,将中间结果存储在不同的变量中非常耗时且分散注意力,而管道让我专注于数据,而不是输入:
x %>% foo
## reason on results and
x %>% foo %>% bar
## reason on results and
x %>% foo %>% bar %>% baz
## etc.
这里的问题是我事先不知道最终的管道是什么,就像@bergant 一样。
打字,如@zx8754,
x %>% print %>% foo %>% print %>% bar %>% print %>% baz
增加了很多开销,对我来说,破坏了 magrittr 的全部目的。
本质上 magrittr 缺少一个简单的运算符,prints 和 pipes 结果。
好消息是制作一个似乎很容易:
`%P>%`=function(lhs, rhs){ print(lhs); lhs %>% rhs }
现在您可以打印管道了:
1:4 %P>% sqrt %P>% sum
## [1] 1 2 3 4
## [1] 1.000000 1.414214 1.732051 2.000000
## [1] 6.146264
我发现如果一个 defines/uses %P>%
和 %>%
的键绑定,原型制作工作流程非常精简(参见 Emacs ESS or RStudio)。
您可以 select 使用发球运算符 (%T>%
) 和 print()
打印哪些结果。 tee-operator 专门用于打印等副作用。
# i.e.
mtcars %>%
group_by(cyl) %T>% print() %>%
sample_frac(0.1) %T>% print() %>%
summarise(res = mean(mpg))
我编写了包 pipes,它可以做几件可能有帮助的事情:
- 使用
%P>%
到print
输出。 - 使用
%ae>%
在输入和输出上使用all.equal
。 - 使用
%V>%
在输出上使用View
,它将为每个相关步骤打开一个查看器。
如果您想查看一些汇总信息,您可以尝试 %summary>%
、%glimpse>%
或 %skim>%
,这将使用 summary
、tibble::glimpse
或 skimr::skim
,或者您可以使用 new_pipe
# devtools::install_github("moodymudskipper/pipes")
library(dplyr)
library(pipes)
res <- mtcars %P>%
group_by(cyl) %P>%
sample_frac(0.1) %P>%
summarise(res = mean(mpg))
#> group_by(., cyl)
#> # A tibble: 32 x 11
#> # Groups: cyl [3]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
#> 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
#> 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
#> 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
#> 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
#> 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
#> 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
#> 8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
#> 9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
#> 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
#> # ... with 22 more rows
#> sample_frac(., 0.1)
#> # A tibble: 3 x 11
#> # Groups: cyl [3]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 26 4 120. 91 4.43 2.14 16.7 0 1 5 2
#> 2 17.8 6 168. 123 3.92 3.44 18.9 1 0 4 4
#> 3 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
#> summarise(., res = mean(mpg))
#> # A tibble: 3 x 2
#> cyl res
#> <dbl> <dbl>
#> 1 4 26
#> 2 6 17.8
#> 3 8 18.7
res <- mtcars %ae>%
group_by(cyl) %ae>%
sample_frac(0.1) %ae>%
summarise(res = mean(mpg))
#> group_by(., cyl)
#> [1] "Attributes: < Names: 1 string mismatch >"
#> [2] "Attributes: < Length mismatch: comparison on first 2 components >"
#> [3] "Attributes: < Component \"class\": Lengths (1, 4) differ (string compare on first 1) >"
#> [4] "Attributes: < Component \"class\": 1 string mismatch >"
#> [5] "Attributes: < Component 2: Modes: character, list >"
#> [6] "Attributes: < Component 2: Lengths: 32, 2 >"
#> [7] "Attributes: < Component 2: names for current but not for target >"
#> [8] "Attributes: < Component 2: Attributes: < target is NULL, current is list > >"
#> [9] "Attributes: < Component 2: target is character, current is tbl_df >"
#> sample_frac(., 0.1)
#> [1] "Different number of rows"
#> summarise(., res = mean(mpg))
#> [1] "Cols in y but not x: `res`. "
#> [2] "Cols in x but not y: `qsec`, `wt`, `drat`, `hp`, `disp`, `mpg`, `carb`, `gear`, `am`, `vs`. "
res <- mtcars %V>%
group_by(cyl) %V>%
sample_frac(0.1) %V>%
summarise(res = mean(mpg))
# you'll have to test this one by yourself