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
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")[]
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()
.