【问题标题】:R data.table gets modified AFTER I've changed it?R data.table 在我更改后被修改?
【发布时间】:2020-12-06 03:15:54
【问题描述】:

这一直困扰着我很长一段时间,我认为 data.table 包有一些我不明白的地方。如果我想要 data.table 的两个“切片”,并将其中一个重命名为新名称,如果我忘记输入“copy”,那么 data.table 会将具有 新名称 的两个对象视为同样的事情。

  1. 是使用“复制”功能解决此问题的唯一系统方法吗?即,如果我不使用“复制”,我会总是得到这种将相同对象视为相同事物的行为吗?
  2. 此功能的用途是什么?与内存存储有关..?如果我决定更改一个 DT 然后使用原始对象,这似乎会导致一些严重的无意错误。此外,如果一个新的 data.table 用户来自 base R,并且不知道这种行为,那么他们的所有代码都会出现一些系统性问题。
  3. 如果 setDT 函数实际上并未将数据表“设置”为新对象,那么它的意义何在?

这是一个说明性示例:

library(data.table)
#####BOTH_SETDT & COPY#####
first_dt <- data.frame(a = c(1,2,3), b = c(9,8,7))
setDT(first_dt)
second_dt <- copy(first_dt)
setDT(second_dt)

first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
#      a b
#1: 0.02 9
#2: 0.04 8
#3: 0.06 7
print(second_dt)
#   a    b
#1: 1 0.18
#2: 2 0.16
#3: 3 0.14

#####BOTH SETDT#####
first_dt <- data.frame(a = c(1,2,3), b = c(9,8,7))
setDT(first_dt)
second_dt <- first_dt
setDT(second_dt)

first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14
print(second_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14

#####SINGLE SETDT#####
first_dt <- data.frame(a = c(1,2,3), b = c(9,8,7))
setDT(first_dt)
second_dt <- first_dt

first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14
print(second_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14

#####AS.DATA.TABLE#####
first_dt <- as.data.table(data.frame(a = c(1,2,3), b = c(9,8,7)))
second_dt <- first_dt

first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14
print(second_dt)
#      a    b
#1: 0.02 0.18
#2: 0.04 0.16
#3: 0.06 0.14

#####AS.DATA.TABLE WITH JUST COPY#####
first_dt <- as.data.table(data.frame(a = c(1,2,3), b = c(9,8,7)))
second_dt <- copy(first_dt)

first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
#      a b
#1: 0.02 9
#2: 0.04 8
#3: 0.06 7
print(second_dt)
#   a    b
#1: 1 0.18
#2: 2 0.16
#3: 3 0.14

#####ANOTHER AS.DATA.TABLE#####
first_dt <- (data.frame(a = c(1,2,3), b = c(9,8,7)))
second_dt <- as.data.table(first_dt)
first_dt <- as.data.table(first_dt)
first_dt[,a:=a/50]
second_dt[,b:=b/50]
print(first_dt)
print(second_dt)

【问题讨论】:

  • ?setDT;该功能适用​​于希望在 data.frame 上使用data.table 接口但内存有限的用户。它与内存和速度有关;相对于 data.frame 对象,副本将使 RAM 使用量翻倍。而且它更快,因为内存分配需要时间。听起来您想要as.data.table,因为它包含副本。这些代码在很大程度上是等效的:setDT(copy(DF)); as.data.table(DF)
  • 啊,我不知道!谢谢科尔!

标签: r data.table


【解决方案1】:

是的,这是故意的,而且非常有意为之。我们希望新用户查看我们的小插曲(例如123)以了解原因。

data.table 在设计时考虑了大型数据集(例如 1GB、10GB 或 50GB)。用这些数据浪费内存可能是分析工作与不可能之间的区别。您可以在 benchmark 中看到这一点的影响——data.table 的几个替代方案根本无法完成 50GB 数据集上的任务,即使机器有足够的内存 (128GB)。

您观察到的引用语义是实现此目标的必要权衡,而不需要溢出到磁盘或并行到不同的机器。

我的建议是注意这种行为,并在分析中使用它来更加小心——您真的需要一个具有相同行数的新表吗?可以用不同的方式实现你想要的吗?

copyas.data.table 在需要时始终可以作为一种解决方法,但我认为成功使用 data.table 的一部分需要稍微改变方法。

PS 如果小插曲中有任何晦涩难懂或难以理解的内容,或者您​​有其他反馈意见,我们很乐意听到 - 请随时提交Issue

【讨论】:

  • 谢谢迈克尔!我没有看到这些小插曲,并且一直在通过反复试验来计算 data.table。这样就搞定了。
  • 嘿迈克尔,我能问一下,这是否意味着对于不将数据表作为输入的函数,如果我必须在多个对象上使用它们,我应该始终以“复制”结束它们? clean_ilostat
  • 乍一看,DT 似乎是一个新对象,在这种情况下,copy 就没有必要了。我不确定我能否提供完全一般的建议;也许这个问题可以帮助? stackoverflow.com/questions/10225098/…
  • 这就是让我从 python pandas 转换为 R data.table 的原因。它很简单,而且速度更快。
  • 真的吗?我实际上一直在考虑切换到 Python,尽管我以前没有真正使用过它。似乎很多新的 AI 包都在 Python 或 Julia 上开发。
猜你喜欢
  • 1970-01-01
  • 2014-12-20
  • 2016-05-05
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 2011-09-13
  • 2020-12-17
相关资源
最近更新 更多