为什么 round 在这个 dplyr 管道中不起作用?

Why doesn't round work in this dplyr pipe?

这是烦人的事情之一,用额外的代码行来解决是一个微不足道的问题,但我不明白为什么我按原样编写代码的尝试不起作用。

我正在尝试在 dplyr 管道中对结果进行舍入,但最后舍入不起作用,我不确定为什么(但我怀疑除法步骤是问题所在)。

这是一个可重现的问题示例:

library(dplyr)

    # Use iris data set for reproducible example

    iris %>% 
      select(Sepal.Length) %>% 
      colSums() / 6 %>% 
      round()

输出:

Sepal.Length 
    146.0833 

我期望输出为 146,就像我这样做时一样(同样的事情,但将中间计算存储在变量“test”中:

test <- iris %>% 
  select(Sepal.Length) %>% 
  colSums() / 6 

round(test)

输出:

Sepal.Length 
         146 

round 在 dplyr 管道中不起作用,无论我将其编码为 round(.,0) 还是如上所述。

似乎 / 6 破坏了 dplyr 链,但我很想了解为什么以及如何在 dplyr 链中正确地编写这一切。

谢谢!

如果我们用 {} 换行,就可以了

iris %>% 
  select(Sepal.Length) %>% 
  {colSums(.) / 6} %>%
  round
#   Sepal.Length 
#     146 

或者另一种选择是

iris %>% 
   select(Sepal.Length) %>%
   colSums %>% 
   divide_by(6) %>%
   round
#Sepal.Length 
#         146 

或者另一种方式是

iris %>%
   select(Sepal.Length) %>%
   colSums() %>% 
   `/`(6) %>% 
   round
#Sepal.Length 
#         146 

或使用summarise

iris %>% 
    summarise(Sepal.Length = round(sum(Sepal.Length)/6))
#  Sepal.Length
#1          146

此问题与运算符优先级有关。根据?Syntax

The following unary and binary operators are defined. They are listed in precedence groups, from highest to lowest.

:: :::  access variables in a namespace
$ @ component / slot extraction
[ [[    indexing
^   exponentiation (right to left)
- + unary minus and plus
:   sequence operator
%any%   special operators (including %% and %/%)
* / multiply, divide
+ - (binary) add, subtract
< > <= >= == != ordering and comparison
!   negation
& &&    and
| ||    or
~   as in formulae
-> ->>  rightwards assignment
<- <<-  assignment (right to left)
=   assignment (right to left)
?   help (unary and binary)

这里的问题是运算符优先级。 %>% 的运算符优先级高于 /,因此 6 %>% round()colSums() / 6 之前先执行。

运算符优先级在页面 ?Syntax 上给出。

:: :::  access variables in a namespace
$ @ component / slot extraction
[ [[    indexing
^   exponentiation (right to left)
- + unary minus and plus
:   sequence operator
%any%   special operators (including %% and %/%) #This also includes pipes %>%
* / multiply, divide #division is after pipes
+ - (binary) add, subtract
< > <= >= == != ordering and comparison
!   negation
& &&    and
| ||    or
~   as in formulae
-> ->>  rightwards assignment
<- <<-  assignment (right to left)
=   assignment (right to left)
?   help (unary and binary)

已经建议的解决方案是明确表示您希望 colSums() / 6 %>% round() 之前先执行。

iris %>% 
  select(Sepal.Length) %>% 
  {colSums(.) / 6} %>%  
  round()

#Sepal.Length 
#         146