处理具有相同类型数据但不同列名的不同数据集的最佳实践

时间:2017-08-14 20:06:30

标签: r data.table

例如,假设我想构建一个用于分析客户交易的包。在一个美好的世界中,每个交易数据集都看起来像

   TransactionId CustomerId TransactionDate
1:             1          1      2017-01-01
2:             2          2      2017-01-15
3:             3          1      2017-05-20
4:             4          3      2017-06-11

然后我可以做出像

这样的好功能
num_customers <- function(transactions){
  length(unique(transactions$CustomerId))
}

实际上,人们使用的列名称各不相同。 (例如,“CustomerId”,“CustomerID”和“cust_id”可能都被不同公司使用)。

我的问题是,对我来说,最好的方法是什么?我计划严重依赖data.table,所以我的直觉是让用户提供从列名到我用作表的属性的映射的映射,如

mytransactions <- data.table(
  transaction_id = c(1L, 2L, 3L, 4L),
  customer_id = c(1L, 2L, 1L, 3L),
  transaction_date = as.Date(c("2017-01-01", "2017-01-15", "2017-05-20", "2017-06-11"))
)
setattr(
  mytransactions, 
  name = "colmap",
  value = c(TransactionID="transaction_id", CustomerID="customer_id", TransactionDate="transaction_date")
)
attributes(mytransactions)

然而,遗憾的是,只要他们对数据进行子集化,就会删除此属性。

attributes(mytransactions[1:2])

1 个答案:

答案 0 :(得分:0)

如果您希望数据具有特定形状和属性集,请定义类。使用S3系统在R中操作非常简单,因为您只需要更改class属性。

让用户创建S3对象的最佳方法是通过一个函数。保持原有的感觉&#34;在调整现有数据集时,让用户提供数据集并命名要用于不同值的列。默认参数值可以使您的包裹代码简明扼要并奖励尊重用户的标准。

transaction_table <- function(dataset,
                              cust_id    = "CustomerId",
                              trans_id   = "TransactionId",
                              trans_date = "TransactionDate") {
  keep_columns <- c(
    CustomerId      = cust_id,
    TransactionId   = trans_id,
    TransactionDate = trans_date
  )
  out_table <- dataset[, keep_columns, with = FALSE]
  setnames(out_table, names(keep_columns))
  setattr(out_table, "class", c("transaction_table", class(out_table)))
  out_table
}


standardized <- transaction_table(
  mytransactions,
  cust_id    = "customer_id",
  trans_id   = "transaction_id",
  trans_date = "transaction_date"
)
standardized
#    CustomerId TransactionId TransactionDate
# 1:          1             1      2017-01-01
# 2:          2             2      2017-01-15
# 3:          1             3      2017-05-20
# 4:          3             4      2017-06-11

作为奖励,您现在可以充分利用S3系统,为通用功能定义特定于类的方法。

print.transaction_table <- function(x, ...) {
  time_range <- range(standardized[["TransactionDate"]])
  formatted_range <- strftime(time_range)
  cat("Transactions from", formatted_range[1], "to", formatted_range[2], "\n")
  NextMethod()
}


print(standardized)
# Transactions from 2017-01-01 to 2017-06-11 
#    CustomerId TransactionId TransactionDate
# 1:          1             1      2017-01-01
# 2:          2             2      2017-01-15
# 3:          1             3      2017-05-20
# 4:          3             4      2017-06-11