在data.table
中可以使用list
类型的列,并且我第一次尝试从此功能中受益。我需要为我的表dt
的每一行存储从rApache Web服务获取的几条注释。每条评论都有一个用户名,日期时间和正文项目。
我没有使用带有一些奇怪的,不寻常的字符的长字符串来将每个邮件与其他邮件分开(例如|
),而使用;
来分隔评论中的每个项目,我想使用列表像这样:
library(data.table)
dt <- data.table(id=1:2,
comment=list(list(
list(username="michele", date=Sys.time(), message="hello"),
list(username="michele", date=Sys.time(), message="world")),
list(
list(username="michele", date=Sys.time(), message="hello"),
list(username="michele", date=Sys.time(), message="world"))))
> dt
id comment
1: 1 <list>
2: 2 <list>
存储为一个特定行添加的所有注释。 (也因为稍后当我需要将其发送回用户界面时转换为JSON
会更容易)
然而,当我尝试模拟在制作过程中我将如何填充表格时(向特定行添加单个注释),R
要么崩溃,要么没有分配我想要的内容然后崩溃:
library(data.table)
> library(data.table)
> dt <- data.table(id=1:2, comment=vector(mode="list", length=2))
> dt$comment
[[1]]
NULL
[[2]]
NULL
> dt[1L, comment := 1] # this works
> dt$comment
[[1]]
[1] 1
[[2]]
NULL
> set(dt, 1L, "comment", list(1, "a")) # assign only `1` and when I try to see `dt` R crashes
Warning message:
In set(dt, 1L, "comment", list(1, "a")) :
Supplied 2 items to be assigned to 1 items of column 'comment' (1 unused)
> dt[1L, comment := list(1, "a")] # R crashes as soon as I run
> dt[1L, comment := list(list(1, "a"))] # any of these two
我知道我试图滥用data.table
,例如设计j
参数的方式允许:
dt[1L, c("id", "comment") := list(1, "a")] # lists in RHS are seen as different columns! not parts of one
问题:那么,有没有办法完成我想要的任务?或者我只需要在变量中取dt$comment
,修改它,然后每次需要更新时重新分配整个列?
答案 0 :(得分:24)
使用:=
:
dt = data.table(id = 1:2, comment = vector("list", 2L))
# assign value 1 to just the first column of 'comment'
dt[1L, comment := 1L]
# assign value of 1 and "a" to rows 1 and 2
dt[, comment := list(1, "a")]
# assign value of "a","b" to row 1, and 1 to row 2 for 'comment'
dt[, comment := list(c("a", "b"), 1)]
# assign list(1, "a") to just 1 row of 'comment'
dt[1L, comment := list(list(list(1, "a")))]
对于最后一种情况,您还需要一个list
,因为data.table
使用list(.)
来查找要通过引用分配给列的值。
使用set
:
dt = data.table(id = 1:2, comment = vector("list", 2L))
# assign value 1 to just the first column of 'comment'
set(dt, i=1L, j="comment", value=1L)
# assign value of 1 and "a" to rows 1 and 2
set(dt, j="comment", value=list(1, "a"))
# assign value of "a","b" to row 1, and 1 to row 2 for 'comment'
set(dt, j="comment", value=list(c("a", "b"), 1))
# assign list(1, "a") to just 1 row of 'comment'
set(dt, i=1L, j="comment", value=list(list(list(1, "a"))))
HTH
我使用当前的开发版本1.9.3,但应该可以在任何其他版本上正常使用。
> sessionInfo()
R version 3.0.3 (2014-03-06)
Platform: x86_64-apple-darwin10.8.0 (64-bit)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] data.table_1.9.3
loaded via a namespace (and not attached):
[1] plyr_1.8.0.99 reshape2_1.2.2 stringr_0.6.2 tools_3.0.3
答案 1 :(得分:12)
只是为了添加更多信息,list
列真正设计的是当每个单元格本身为vector
时:
> DT = data.table(a=1:2, b=list(1:5,1:10))
> DT
a b
1: 1 1,2,3,4,5
2: 2 1,2,3,4,5,6,
> sapply(DT$b, length)
[1] 5 10
请注意b
列中矢量的漂亮打印。这些逗号只是用于显示,每个单元格实际上是一个向量(如上面的sapply
命令所示)。另请注意b
第二项上的尾随逗号。这表明向量比显示的长(data.table只显示前6项)。
或者,更像你的例子:
> DT = data.table(id=1:2, comment=list( c("michele", Sys.time(), "hello"),
c("michele", Sys.time(), "world") ))
> DT
id comment
1: 1 michele,1395330180.9278,hello
2: 2 michele,1395330180.9281,world
您尝试执行的操作不仅包含list
列,还将list
放入每个单元格中,这就是显示<list>
的原因。此外,如果将命名的列表放入每个单元格中,请注意所有这些名称都会占用空间。如果可能,list
列vectors
可能会更容易。