之间有什么区别和.data?

问题描述

我正在尝试对dplyr使用点(“。”)和.data使用dplyr代词有更深入的了解。我编写的激发这篇文章代码看起来像这样:

cat_table <- tibble(
  variable = vector("character"),category = vector("numeric"),n        = vector("numeric")
) 

for(i in c("cyl","vs","am")) {
  cat_stats <- mtcars %>% 
    count(.data[[i]]) %>% 
    mutate(variable = names(.)[1]) %>%
    rename(category = 1)
  
  cat_table <- bind_rows(cat_table,cat_stats)
}
# A tibble: 7 x 3
  variable category     n
  <chr>       <dbl> <dbl>
1 cyl             4    11
2 cyl             6     7
3 cyl             8    14
4 vs              0    18
5 vs              1    14
6 am              0    19
7 am              1    13

代码可以实现我想要的功能,而实际上并不是该问题的重点。我只是提供它作为背景。

我试图对为什么做我想做的事情有更深的了解。更具体地说,为什么我不能互换使用..data。我已经读过Programming with dplyr文章,但我想..data都意味着“我们到此为止的结果。”但是,似乎我在简化关于它们如何工作的思维模型,因为在以下.data内使用names()时出现错误

mtcars %>% 
  count(.data[["cyl"]]) %>% 
  mutate(variable = names(.data)[1])
Error: Problem with `mutate()` input `variable`.
x Can't take the `names()` of the `.data` pronoun
ℹ Input `variable` is `names(.data)[1]`.
Run `rlang::last_error()` to see where the error occurred.

当我在.中使用count()时,我得到了意外的结果:

mtcars %>% 
  count(.[["cyl"]]) %>% 
  mutate(variable = names(.)[1])
  .[["cyl"]]  n   variable
1          4 11 .[["cyl"]]
2          6  7 .[["cyl"]]
3          8 14 .[["cyl"]]

我怀疑它与以下内容有关:“请注意,.data不是数据帧;它是一个特殊的构造,代词,它使您可以直接使用.data $ x或间接使用.data [[var]]。不要期望其他功能可以使用它。”,dplyr编程中的文章。这告诉我什么.data 不是-一个数据框-但是,我仍然不确定.data 是什么以及如何它不同于.

我试图这样解决

mtcars %>% 
  count(.data[["cyl"]]) %>% 
  mutate(variable = list(.data))

但是,结果<S3: rlang_data_pronoun>对我来说并不意味着任何可以帮助我理解的东西。如果外面有人对此有更好的了解,我将简要听一听。谢谢!

解决方法

首先,我认为.data的意图有些混乱,直到人们也考虑了其同级代词.env

.magrittr::%>%设置和使用的点;由于dplyr重新导出,它就在那里。每当您引用它时,它都是真实的对象,因此names(.)nrow(.)等都可以正常工作。它确实反映了管道中到目前为止的数据。

另一方面,

.data是在rlang中定义的,目的是消除符号分辨率的歧义。与.env一起使用时,它可以使您清楚地知道要解析特定符号的位置(预期有歧义时)。根据{{​​3}},我认为这是一个明确的对比:

disp <- 10
mtcars %>% mutate(disp = .data$disp * .env$disp)
mtcars %>% mutate(disp = disp * disp)

但是,如帮助页面中所述,.data(和.env)只是一个“代词”(我们有动词,所以现在也有了代词),因此它只是一个指针向整洁的内部解释要解析符号的位置。这只是种提示。

所以你的声明

..data都只表示“我们到管道的这一点为止的结果。”

是不正确的:.代表到目前为止的数据,.data只是内部的声明性提示。


考虑另一种考虑.data的方式:假设我们有两个函数完全消除了引用符号所针对的环境的歧义:

  • get_internally,此符号必须始终引用列名称,如果该列不存在,它将不与封闭环境联系;和
  • get_externally,此符号在封闭环境中必须始终引用变量/对象,永远不会与列匹配。

在这种情况下,翻译以上示例,可能会使用

disp <- 10
mtcars %>%
  mutate(disp = get_internally(disp) * get_externally(disp))

在那种情况下,似乎get_internally不是框架,因此您无法调用names(get_internally)并期望它做一些有意义的事情(NULL除外)。就像names(mutate)

因此,请勿将.data视为对象,而应将其视为消除符号环境歧义的机制。我认为它使用的$既简短又易于使用,并且绝对具有误导性:它不是listenvironment的对象,即使它是这样处理。

顺便说一句:可以为$编写任何S3方法,使任何分类的对象看起来像框架/环境:

`$.quux` <- function(x,nm) paste0("hello,",nm,"!")
obj <- structure(0,class = "quux")
obj$r2evans
# [1] "hello,r2evans!"
names(obj)
# NULL

$访问器的存在并不总是表示该对象是框架/环境。)

,

.变量来自magrittr,与管道有关。这意味着“将值传递到此表达式中”。通常,对于管道,上一个表达式中的值在下一个表达式中成为参数1,但这为您提供了在其他参数中使用它的方式。

.data对象是dplyr的特殊对象(尽管它是在rlang包中实现的)。它本身没有任何有用的值,但是在dplyr“整洁的评估”框架中进行评估时,它以多种方式起作用,就好像它是数据帧/小标题的值一样。您可以在有歧义的情况下使用它:如果您的变量与数据框列的名称为foo,则.data$foo表示它是您想要的列(如果找不到,则会出现错误,不像data$foo会得到NULL)。您也可以使用.env$foo来表示忽略该列,并从调用环境中获取该变量。

.data.env都专用于dplyr函数和其他使用相同特殊评估方案的函数,而.是常规变量,可以在任何函数中使用

编辑后添加:您问为什么names(.data)不起作用。如果@ r2evans出色的答案还不够,那么请采取另一种做法:我怀疑问题是names()不是dplyr函数,即使names.rlang_fake_data_pronounrlang。因此,表达式names(.data)是使用常规评估而不是整洁评估的。该方法不知道要查找哪个数据帧,因为在那种情况下没有一个。

,

从理论上讲:

.是magrittr代词。它表示与%>%一起传递的整个输入(与dplyr一起使用时通常是一个数据帧)。

.data是整齐的代词。从技术上讲,它根本不是数据框架,而是评估环境。

在实践上:

.不会被dplyr修改。它保持恒定,直到到达下一个管道表达式为止。另一方面,.data始终是最新的。这意味着您可以引用以前创建的变量:

mtcars %>%
  mutate(
    cyl2 = cyl + 1,am3 = .data[["cyl2"]] + 10
  )

对于分组的数据框,您还可以引用列 slices

mtcars %>%
  group_by(cyl) %>%
  mutate(cyl2 = .data[["cyl"]] + 1)

如果改用.[["cyl"]],则整个数据帧将被子集化,并且由于输入大小与组切片大小不同而导致错误。棘手的!

,

比较req.connection.setTimeout(60 * 1000);'sec-fetch-mode': 'navigate','sec-fetch-dest': 'document',

'sec-fetch-mode': 'cors','sec-fetch-dest': 'empty',

mtcars %>% count(.data[["cyl"]])实际上只是先前的结果。所以第一个类似于:

mtcars %>% count(.[["cyl"]])

第二个是通过字符串“ cyl”查找变量并将先前的结果作为变量的搜索路径的简写。例如,假设您拼写了变量名:

mtcars %>% count(.[["cyl"]])
  .[["cyl"]]  n
1          4 11
2          6  7
3          8 14


mtcars %>% count(.data[["cyl"]])
  cyl  n
1   4 11
2   6  7
3   8 14

使用.不会引发错误,因为索引到不存在的列是返回. <- mtcars count(.,.[["cyl"]]) 的有效base-R操作。

使用mtcars %>% count(.[["cyll"]]) n 1 32 mtcars %>% count(.data[["cyll"]]) Error: Must group by variables found in `.data`. * Column `cyll` is not found. 会抛出异常,因为使用了不存在的变量:

.

也抛出。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...