Data.table: 使用功能setkey时出错

创建于 2019-04-09  ·  3评论  ·  资料来源: Rdatatable/data.table

我知道如何避免此错误,但我不知道为什么以这种方式运行会发生此错误。

datain <- data.frame(
 chrom = c("chr17", "chr4", "chr5", "chr13"),
 map = c(81061047, 106061533, 40102442, 73791553),
 rs = c("rs75954926", "rs7679673", "rs7708610", "rs78341008"),
 start = c(79061048, 104061534, 38102443, 71791554),
 end = c(83061048, 108061534, 42102443, 75791554)
)
datain
datain$chr<-datain$chrom
setDT(datain)
setkey(datain, chr, start, end)
datain

谢谢!

亚历克斯

最有用的评论

iiuc,当不加修改地复制列或列表元素时,内存地址将相同,并且设置键将“使事情变得混乱”。
使用copy()

# KO
l <- list(x = c(9, 1), y = c(9, 1))
l[["z"]] <- l[["x"]]
l
setDT(l, key  = "x")[]

address(l$x) == address(l$z)
# TRUE

# OK
l <- list(x = c(9, 1), y = c(9, 1))
l[["z"]] <- copy(l[["x"]])
l
setDT(l, key  = "x")[]

所有3条评论

我可以在Windows 10和macOS 10.13.6上使用data.table 1.12.0重现此内容。 将我的macOS系统升级为data.table 1.12.2之后,我可以确认以下所有示例给出的结果相同。

一个更简单的示例:

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> d$x2 <- d$x
> d
      x y    x2
1  chr9 1  chr9
2 chr13 2 chr13
3  chr3 3  chr3
4 chr11 4 chr11
> setDT(d)
> setkey(d,x2,y)
> d
       x y    x2
1:  chr9 4  chr9
2: chr13 2 chr13
3:  chr3 3  chr3
4: chr11 1 chr11

当您直接用setDT分配密钥时,也会发生这种情况(这可能是因为setDT使用setkeyv来设置密钥):

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> d$x2 <- d$x
> d
      x y    x2
1  chr9 1  chr9
2 chr13 2 chr13
3  chr3 3  chr3
4 chr11 4 chr11
> setDT(d, key = c("x2","y"))
> d
       x y    x2
1:  chr9 4  chr9
2: chr13 2 chr13
3:  chr3 3  chr3
4: chr11 1 chr11

如您所见, y列的顺序已更改,而其他列的顺序未更改。 显然,仅当您以data.frame方式复制列,然后使用setDT然后使用setkey时,才会发生这种情况。 请考虑以下五种情况,它们都能达到预期的结果:

1)不复制数据框列

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> d
      x y
1  chr9 1
2 chr13 2
3  chr3 3
4 chr11 4
> setDT(d)
> setkey(d,x)
> d
       x y
1: chr11 4
2: chr13 2
3:  chr3 3
4:  chr9 1

2)在数据框中创建一个任意的新列

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> set.seed(1)
> d$x2 <- paste0("chr",sample(17)[1:4])
> d
      x y    x2
1  chr9 1  chr5
2 chr13 2  chr6
3  chr3 3  chr9
4 chr11 4 chr13
> setDT(d)
> setkey(d,x2,y)
> d
       x y    x2
1: chr11 4 chr13
2:  chr9 1  chr5
3: chr13 2  chr6
4:  chr3 3  chr9

3)通过对现有列进行采样并在其中粘贴一些extr字符来创建新列

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> set.seed(1)
> d$x2 <- paste0("new_",sample(d$x,4))
> d
      x y        x2
1  chr9 1 new_chr13
2 chr13 2 new_chr11
3  chr3 3  new_chr3
4 chr11 4  new_chr9
> setDT(d)
> setkey(d,x2,y)
> d
       x y        x2
1: chr13 2 new_chr11
2:  chr9 1 new_chr13
3:  chr3 3  new_chr3
4: chr11 4  new_chr9

4)通过仅对现有列进行采样来创建新列

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> set.seed(1)
> d$x2 <- sample(d$x,4)
> d
      x y    x2
1  chr9 1 chr13
2 chr13 2 chr11
3  chr3 3  chr3
4 chr11 4  chr9
> setDT(d)
> setkey(d,x2,y)
> d
       x y    x2
1: chr13 2 chr11
2:  chr9 1 chr13
3:  chr3 3  chr3
4: chr11 4  chr9

5)以data.table方式复制列

> set.seed(1)
> d <- data.frame(x = paste0("chr",sample(17)[3:6]), y = 1:4)
> d
      x y
1  chr9 1
2 chr13 2
3  chr3 3
4 chr11 4
> setDT(d)
> d[, x2 := x][]
       x y    x2
1:  chr9 1  chr9
2: chr13 2 chr13
3:  chr3 3  chr3
4: chr11 4 chr11
> setkey(d,x2,y)
> d
       x y    x2
1: chr11 4 chr11
2: chr13 2 chr13
3:  chr3 3  chr3
4:  chr9 1  chr9

尽管此错误似乎发生在(非常)特定的用例中,但这对我来说可能很关键,因为我在多个生产系统中使用了setkey 。 将检查此特定情况是否在我的生产代码中发生。

确认@jaapwalhout的观察(使用data.table_1.12.3)。
同样,(i)认为它可能与因素有关,但与因素无关(也可能是字符或整数),(ii)无论键是什么(x或y),它都会发生。
下面是一个更简单的可重现示例。
作业中的警告可能是相关的,但我不确定是否理解。

options(datatable.verbose = TRUE)

## KO
d <- data.frame(x = c(9, 1), y = c(9, 1))
d$x2 <- d$x
d
#   x y x2
# 1 9 9  9
# 2 1 1  1
setDT(d, key  = "x")[]
# forder took 0 sec
# reorder took 0 sec
#    x y x2
# 1: 9 1  9
# 2: 1 9  1

## KO
d <- data.frame(x = c("9", "1"), y = c(9, 1), stringsAsFactors = FALSE)
d$x2 <- d$x
d
#   x y x2
# 1 9 9  9
# 2 1 1  1
setDT(d, key  = "x")[]
# forder took 0 sec
# reorder took 0 sec
#    x y x2
# 1: 9 1  9
# 2: 1 9  1

## OK (with warning)
d <- data.frame(x = c("9", "1"), y = c(9, 1))
setDT(d)
d$x2 <- d$x
# Assigning to all 2 rows
# RHS for item 1 has been duplicated because NAMED is 2, but then is being plonked. length(values)==2; length(cols)==1)
setkey(d, y, verbose = TRUE)[]
# forder took 0 sec
# reorder took 0 sec
#    x y x2
# 1: 1 1  1
# 2: 9 9  9

iiuc,当不加修改地复制列或列表元素时,内存地址将相同,并且设置键将“使事情变得混乱”。
使用copy()

# KO
l <- list(x = c(9, 1), y = c(9, 1))
l[["z"]] <- l[["x"]]
l
setDT(l, key  = "x")[]

address(l$x) == address(l$z)
# TRUE

# OK
l <- list(x = c(9, 1), y = c(9, 1))
l[["z"]] <- copy(l[["x"]])
l
setDT(l, key  = "x")[]
此页面是否有帮助?
0 / 5 - 0 等级