Data.table: erro ao usar a função setkey

Criado em 9 abr. 2019  ·  3Comentários  ·  Fonte: Rdatatable/data.table

Sei como evitar esse erro, mas não sei por que esse erro acontece se eu o executo dessa forma.

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

Obrigado!

Alex

bug

Comentários muito úteis

iiuc, ao duplicar uma coluna ou elemento de lista sem modificação, o endereço de memória será o mesmo e definir a chave irá "bagunçar as coisas".
Funciona bem ao usar 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")[]

Todos 3 comentários

Posso reproduzir isso com data.table 1.12.0 no Windows 10 e no macOS 10.13.6. Depois de atualizar meu sistema macOS para data.table 1.12.2, posso confirmar que todos os exemplos abaixo apresentam o mesmo resultado.

Um exemplo um pouco mais simples:

> 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

Isso também acontece quando você atribui a chave diretamente com setDT (o que poderia ser esperado, pois setDT usa setkeyv para definir as chaves):

> 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

Como você pode ver, a ordem da coluna y -coluna foi alterada, enquanto a ordem das outras colunas não. Aparentemente, isso só acontece quando você copia uma coluna da maneira data.frame, usa setDT e, em seguida, setkey . Considere os cinco casos a seguir, que fornecem o resultado pretendido:

1) não copiar uma coluna de dataframe

> 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) criar uma nova coluna arbitrária no dataframe

> 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) criar uma nova coluna por amostragem de uma coluna existente e colar alguns caracteres extras nela

> 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) criar uma nova coluna apenas amostrando uma coluna existente

> 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) copiar uma coluna da maneira 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

Embora esse bug pareça ocorrer em um caso de uso (muito) específico, isso pode ser crítico para mim porque eu uso setkey em vários sistemas de produção. Irá verificar se este caso específico ocorre no meu código de produção.

Confirmando @jaapwalhout 's observações (com data.table_1.12.3).
Além disso, (i) pensei que poderia estar relacionado a fatores, mas não está (acontece também com caractere ou inteiro), (ii) acontece independentemente da chave (x ou y).
Abaixo, um exemplo reproduzível mais simples.
O aviso na tarefa pode estar relacionado, mas não tenho certeza de entendê-lo.

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, ao duplicar uma coluna ou elemento de lista sem modificação, o endereço de memória será o mesmo e definir a chave irá "bagunçar as coisas".
Funciona bem ao usar 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")[]
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

nachti picture nachti  ·  3Comentários

tcederquist picture tcederquist  ·  3Comentários

symbalex picture symbalex  ·  3Comentários

mattdowle picture mattdowle  ·  3Comentários

st-pasha picture st-pasha  ·  3Comentários