簡體   English   中英

R:如何在 S3 類中使用和擴展 data.table

[英]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.

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