[英]R: how to use and extend data.table in an S3 class
我想創建一個 S3 類,它通過添加將由該類的其他方法使用的屬性來擴展data.table
。 在下面的示例中,我添加了一個屬性colMeas
,它保存帶有測量值的列的名稱:
library(data.table)
myclass <- function(dt, colMeas) {
stopifnot(data.table::is.data.table(dt))
data.table::setattr(dt, "colMeas", colMeas)
data.table::setattr(dt, "class", union("myclass", class(dt)))
}
is.myclass <- function(obj) inherits(obj, "myclass")
我有一個修改現有測量列的方法:
modCol <- function(obj, arg) {
UseMethod("modCol")
}
# Modify the existing column
modCol.myclass <- function(obj, arg) {
stopifnot(is.myclass(obj))
stopifnot(is.numeric(arg))
colMeas <- attr(obj, "colMeas")
obj[,
(colMeas) := get(colMeas) + arg]
}
以及添加新列的方法:
addCol <- function(obj, arg) {
UseMethod("addCol")
}
# Add a column
addCol.myclass <- function(obj, arg) {
stopifnot(is.myclass(obj))
stopifnot(is.numeric(arg))
colMeas <- attr(obj, "colMeas")
obj[,
colNew := get(colMeas) + arg]
data.table::setattr(obj, "colNew", "colNew")
}
我使用的一切如下:
library(data.table)
dt = data.table(x = 1:10,
y = rep(1, 10))
myclass(dt, colMeas = "y")
modCol(dt, 10)
addCol(dt, 10)
這使:
> dt
x y colNew
1: 1 11 21
2: 2 11 21
3: 3 11 21
4: 4 11 21
5: 5 11 21
6: 6 11 21
7: 7 11 21
8: 8 11 21
9: 9 11 21
10: 10 11 21
> attributes(dt)
$names
[1] "x" "y" "colNew"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
$class
[1] "myclass" "data.table" "data.frame"
$.internal.selfref
<pointer: 0x7f841e016ee0>
$colMeas
[1] "y"
$colNew
[1] "colNew"
問題更多是關於 R/S3“學說”。 在上面的方法中,我正在“就地”修改data.table
對象,我可以在不將結果分配給新對象的情況下調用這些函數。 這是在 S3 類中處理data.table
對象的正確方法嗎? 或者我應該將顯式return(obj)
添加到所有函數,然后像這樣分配結果:
dt = myclass(dt, colMeas = "y")
dt = modCol(dt, 10)
dt = addCol(dt, 10)
這不會導致過度復制dt
對象嗎?
我會投票Yes來修改它,也就是說,不要讓它有必要捕獲返回的值。
(在考慮這個回復時我兩次改變主意,但現在我確定了)。
data.table 中有幾個 function 可以就地修改對象,例如setnames(...)
。 這有明確的優先級。
data.table 代碼庫中還有一個通用哲學可以通過參考來工作,這是將其與 data.frames 區分開來的重要特征
融入這種設計理念聽起來是正確的做法。
注意:我認為隱形返回 data.table object 還是不錯的。
您的代碼似乎依賴於union()
的(AFAIK)未記錄的屬性,它是保留順序的。 你會希望“myclass”出現在班級列表的第一位,以便准確調度。 所以我建議你用append()
而不是union()
更新你的類列表:
data.table::setattr(dt, "class", append(c("myclass"), class(dt)))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.