[英]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_pronoun
是rlang
中的一種方法。 因此,表達式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.