J'ai souvent besoin de transposer un data.table
, Chaque fois qu'il faut plusieurs lignes de code et je me demande s'il y a une meilleure solution que la mienne.
si nous prenons un échantillon de table
library(data.table)
mydata <- data.table(col0=c("row1","row2","row3"),
col1=c(11,21,31),
col2=c(12,22,32),
col3=c(13,23,33))
mydata
# col0 col1 col2 col3
# row1 11 12 13
# row2 21 22 23
# row3 31 32 33
et juste le transposer avec t()
, il sera transposé à la matrice avec conversion en type character
, tandis que l'application de data.table
à une telle matrice perdra row.names
:
t(mydata)
# [,1] [,2] [,3]
# col0 "row1" "row2" "row3"
# col1 "11" "21" "31"
# col2 "12" "22" "32"
# col3 "13" "23" "33"
data.table(t(mydata))
# V1 V2 V3
# row1 row2 row3
# 11 21 31
# 12 22 32
# 13 23 33
j'ai donc dû écrire une fonction pour cela:
tdt <- function(inpdt){
transposed <- t(inpdt[,-1,with=F]);
colnames(transposed) <- inpdt[[1]];
transposed <- data.table(transposed, keep.rownames=T);
setnames(transposed, 1, names(inpdt)[1]);
return(transposed);
}
tdt(mydata)
# col0 row1 row2 row3
# col1 11 21 31
# col2 12 22 32
# col3 13 23 33
y a-t-il quelque chose que je pourrais optimiser ici ou le faire de manière "plus agréable"?
Pourquoi pas simplement melt
et dcast
le data.table
?
require(data.table)
dcast(melt(mydata, id.vars = "col0"), variable ~ col0)
# variable row1 row2 row3
# 1: col1 11 21 31
# 2: col2 12 22 32
# 3: col3 13 23 33
Voici une solution alternative qui utilise uniquement data.table
et c'est plus proche de l'idée originale d'utiliser t
pour transposer.
mydata[, data.table(t(.SD), keep.rownames=TRUE), .SDcols=-"col0"]
## rn V1 V2 V3
## 1: col1 11 21 31
## 2: col2 12 22 32
## 3: col3 13 23 33
Si la conservation des noms de domaine est importante, setnames
peut être utilisé. Certes, cela devient un peu maladroit et la solution de refonte est probablement préférable.
setnames(mydata[, data.table(t(.SD), keep.rownames=TRUE), .SDcols=-"col0"],
mydata[, c('rn', col0)])[]
## rn row1 row2 row3
## 1: col1 11 21 31
## 2: col2 12 22 32
## 3: col3 13 23 33
Les documents actuels montrent une méthode transpose
intégrée. Je ne sais pas quand il a été ajouté, mais apparemment c'était nécessaire!
df <- as.data.frame(t(mydata))
est ce que j'ai essayé et df
est un data.frame
et les noms de colonne sur mydata
sont maintenant des noms de ligne sur df
Voici une solution qui utilise un wrapper pour ranger la sortie de la fonction data.table transpose
.
Avec des ensembles de données vraiment volumineux, cela semble être plus efficace que l'approche dcast/melt (je l'ai testé sur un ensemble de données de 8000 lignes x 29000 colonnes, la fonction ci-dessous fonctionne en environ 3 minutes mais dcast/melt s'est écrasé R):
# Function to clean up output of data.table transpose:
transposedt <- function(dt, varlabel) {
require(data.table)
dtrows = names(dt)
dtcols = as.list(c(dt[,1]))
dtt = transpose(dt)
dtt[, eval(varlabel) := dtrows]
setnames(dtt, old = names(dtt), new = c(dtcols[[1]], eval(varlabel)))
dtt = dtt[-1,]
setcolorder(dtt, c(eval(varlabel), names(dtt)[1:(ncol(dtt) - 1)]))
return(dtt)
}
# Some dummy data
mydt <- data.table(col0 = c(paste0("row", seq_along(1:100))),
col01 = c(sample(seq_along(1:100), 100)),
col02 = c(sample(seq_along(1:100), 100)),
col03 = c(sample(seq_along(1:100), 100)),
col04 = c(sample(seq_along(1:100), 100)),
col05 = c(sample(seq_along(1:100), 100)),
col06 = c(sample(seq_along(1:100), 100)),
col07 = c(sample(seq_along(1:100), 100)),
col08 = c(sample(seq_along(1:100), 100)),
col09 = c(sample(seq_along(1:100), 100)),
col10 = c(sample(seq_along(1:100), 100)))
# Apply the function:
mydtt <- transposedt(mydt, "myvariables")
# View the results:
> mydtt[,1:10]
myvariables row1 row2 row3 row4 row5 row6 row7 row8 row9
1: col01 58 53 14 96 51 30 26 15 68
2: col02 6 72 46 62 69 9 63 32 78
3: col03 21 36 94 41 54 74 82 64 15
4: col04 68 41 66 30 31 78 51 67 26
5: col05 49 30 52 78 73 71 5 66 44
6: col06 89 35 79 67 6 88 62 97 73
7: col07 66 15 27 29 58 40 35 82 57
8: col08 55 47 83 30 23 65 48 56 87
9: col09 41 10 21 33 55 81 94 25 34
10: col10 35 17 41 44 21 66 69 61 46
Ce qui est également utile, c'est que les colonnes (ex lignes) apparaissent dans leur ordre d'origine et vous pouvez nommer la colonne des variables quelque chose de significatif.