簡體   English   中英

有什么區別。 和.data?

[英]What is the difference between . and .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可互換。 我已經閱讀了dplyr 文章的編程,但我想在我看來,兩者都是. .data僅表示“我們在管道中的這一點的結果”。 但是,似乎我過度簡化了我的心理 model 它們的工作方式,因為當我在下面的names()中使用.data時出現錯誤:

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"]]

我懷疑它與“注意 that.data 不是數據框;它是一個特殊的結構,一個代詞,它允許您直接訪問當前變量,with.data$x 或間接 with.data[ [var]]。不要指望其他功能可以使用它,”來自使用 dplyr 編程一文。 這告訴我.data不是什么——一個數據框——但是,我仍然不確定.data什么以及它與 .data 有何不同. .

我試着像這樣弄清楚:

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

但是,結果<S3: rlang_data_pronoun>對我來說沒有任何幫助我理解的意義。 如果有人對此有更好的了解,我將不勝感激。 謝謝!

在前面,我認為.data的意圖有點令人困惑,直到人們也考慮它的兄弟代詞.env

. magrittr::%>%設置和使用的東西; 由於dplyr重新出口它,它就在那里。 每當您引用它時,它都是真正的 object,因此names(.)nrow(.)等都按預期工作。 確實反映了管道中到目前為止的數據。

另一方面, .data是在rlang中定義的,目的是消除符號解析的歧義。 .env ,它可以讓您非常清楚地知道您希望在哪里解決特定符號(當預期有歧義時)。 ?.data ,我認為這是一個清晰的對比:

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視為 object,將其視為消除符號環境歧義的機制。 我認為它使用的$既簡潔/易於使用又絕對具有誤導性:它不是類似list或類似environment的 object,即使它被視為這樣。

順便說一句:可以為$編寫任何 S3 方法,使任何分類對象看起來像一個框架/環境:

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

$訪問器的存在並不總是意味着 object 是一個框架/環境。)

. 變量來自magrittr ,與管道有關。 它的意思是“被輸送到這個表達式中的值”。 通常對於管道,前一個表達式的值在下一個表達式中成為參數 1,但這為您提供了一種在其他參數中使用它的方法。

.data object 對dplyr是特殊的(盡管它是在rlang包中實現的)。 它本身沒有任何有用的價值,但是當在dplyr “tidy eval”框架中進行評估時,它在許多方面的作用就好像它是數據幀/tibble 的值一樣。 當有歧義時使用它:如果你有一個與 dataframe 列同名的變量foo ,那么.data$foo說它是你想要的列(如果找不到它會給出錯誤,不像data$foo那樣將給出NULL )。 您也可以使用.env$foo來表示忽略該列並從調用環境中獲取變量。

.data.env都特定於dplyr函數和其他使用相同特殊評估方案的函數,而. 是一個正則變量,可以在任何 function 中使用。

編輯添加:您問為什么names(.data)不起作用。 如果@r2evans 出色的答案還不夠,這里有一個不同的看法:我懷疑問題是names()不是dplyr function,即使names.rlang_fake_data_pronounrlang中的一種方法。 因此,表達式names(.data)是使用常規評估而不是整潔評估來評估的。 該方法不知道要查看什么 dataframe,因為在那種情況下沒有。

在理論層面上:

. 是 magrittr 代詞。 它表示使用%>%管道輸入的整個輸入(與 dplyr 一起使用時通常是數據幀)。

.data是整潔的評估代詞。 從技術上講,它根本不是一個數據框,它是一個評估環境。

在實踐層面:

. 永遠不會被 dplyr 修改。 它保持不變,直到到達下一個管道表達式。 另一方面, .data始終是最新的。 這意味着您可以引用以前創建的變量:

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

在分組數據框的情況下,您還可以參考列切片

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

如果您使用.[["cyl"]]代替,則整個數據幀將被子集化,並且您將收到錯誤消息,因為輸入大小與組切片大小不同。 棘手!

比較mtcars %>% count(.data[["cyl"]])mtcars %>% count(.[["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"]])

第二個是通過字符串“cyl”查找變量並將之前的結果作為變量的搜索路徑的簡寫。 例如,假設您拼錯了變量名:

mtcars %>% count(.[["cyll"]])
   n
1 32

mtcars %>% count(.data[["cyll"]])
Error: Must group by variables found in `.data`.
* Column `cyll` is not found.

使用. 不會拋出錯誤,因為索引到不存在的列是返回NULL的有效 base-R 操作。

使用.data會拋出,因為使用了不存在的變量:

mtcars %>% count(cyll)

還扔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM