ligne par ligne des opérations et des mises à jour dans les données.table
J'ai fini avec un big data.table et je dois faire des opérations par ligne. (oui... je sais que ce n'est clairement pas ce que sont les données.le tableau sont pour)
R) set.seed(1)
R) DT=data.table(matrix(rnorm(100),nrow=10))
R) DT[,c('a','b'):=list(1:10,2:11)]
R) DT
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 a b
1: -0.6264538107 1.51178116845 0.91897737161 1.35867955153 -0.1645235963 0.3981058804 2.40161776050 0.475509528900 -0.5686687328 -0.5425200310 1 2
2: 0.1836433242 0.38984323641 0.78213630073 -0.10278772734 -0.2533616801 -0.6120263933 -0.03924000273 -0.709946430922 -0.1351786151 1.2078678060 2 3
3: -0.8356286124 -0.62124058054 0.07456498337 0.38767161156 0.6969633754 0.3411196914 0.68973936245 0.610726353489 1.1780869966 1.1604026157 3 4
4: 1.5952808021 -2.21469988718 -1.98935169586 -0.05380504058 0.5566631987 -1.1293630961 0.02800215878 -0.934097631644 -1.5235668004 0.7002136495 4 5
5: 0.3295077718 1.12493091814 0.61982574789 -1.37705955683 -0.6887556945 1.4330237017 -0.74327320888 -1.253633400239 0.5939461876 1.5868334545 5 6
6: -0.8204683841 -0.04493360902 -0.05612873953 -0.41499456330 -0.7074951570 1.9803998985 0.18879229951 0.291446235517 0.3329503712 0.5584864256 6 7
7: 0.4874290524 -0.01619026310 -0.15579550671 -0.39428995371 0.3645819621 -0.3672214765 -1.80495862889 -0.443291873218 1.0630998373 -1.2765922085 7 8
8: 0.7383247051 0.94383621069 -1.47075238390 -0.05931339671 0.7685329245 -1.0441346263 1.46555486156 0.001105351632 -0.3041839236 -0.5732654142 8 9
9: 0.5757813517 0.82122119510 -0.47815005511 1.10002537198 -0.1123462122 0.5697196274 0.15325333821 0.074341324152 0.3700188099 -1.2246126149 9 10
10: -0.3053883872 0.59390132122 0.41794156020 0.76317574846 0.8811077265 -0.1350546039 2.17261167036 -0.589520946188 0.2670987908 -0.4734006364 10 11
Dire que je veux le min
travers de tous les Vi
colonnes, ligne par ligne, j'ai utilisé apply
quand j'ai été en utilisant data.frame
.
apply(DT[,paste0('V',1:10),with=FALSE],FUN=min,MAR=1)
[1] -0.6264538107 -0.7099464309 -0.8356286124 -2.2146998872 -1.3770595568 -0.8204683841 -1.8049586289 -1.4707523839 -1.2246126149 -0.5895209462
Afin que je puisse mettre à jour facilement.
Ok, maintenant dire que je veux mettre à jour le min
et max
à la fois (bien sûr c'est un exemple donc je l'ai pris juste 2 choses, mais dans la vraie vie, qui serait de 10...)
f = function(x){return(c(max=max(x),min=min(x)))}
new=apply(DT[,paste0('V',1:10),with=FALSE],FUN=f,MAR=1)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
max 2.4016177605 1.2078678060 1.1780869966 1.595280802 1.586833455 1.9803998985 1.063099837 1.465554862 1.100025372 2.1726116704
min -0.6264538107 -0.7099464309 -0.8356286124 -2.214699887 -1.377059557 -0.8204683841 -1.804958629 -1.470752384 -1.224612615 -0.5895209462
Je voudrais écrire
DT[,rownames(new):=new]
mais cela ne fonctionne pas, voici donc mes questions
- En utilisant ma méthode, comment puis-je transformer
new
que j'ai mise à jourDT
à la fois ? - Sont-il une meilleure approche (qui me permettrait de mettre à jour plusieurs colonnes à la fois, avec le résultat d'un calcul de ligne)
MODIFIER: j'ai trouvé une solution pour le 1, mais c'est LAID, en fait, Il est étrange que :=
ne pas manipuler matrix
, je suis assez sûr il sert à être le cas
DT[,c('a1','a2'):=data.table(matrix(apply(DT[,paste0('V',1:10),with=FALSE],FUN=f,MAR=1),byrow=T,nrow=10))]
R) DT
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 a b
1: -0.6264538107 1.51178116845 0.91897737161 1.35867955153 -0.1645235963 0.3981058804 2.40161776050 0.475509528900 -0.5686687328 -0.5425200310 1 2
2: 0.1836433242 0.38984323641 0.78213630073 -0.10278772734 -0.2533616801 -0.6120263933 -0.03924000273 -0.709946430922 -0.1351786151 1.2078678060 2 3
3: -0.8356286124 -0.62124058054 0.07456498337 0.38767161156 0.6969633754 0.3411196914 0.68973936245 0.610726353489 1.1780869966 1.1604026157 3 4
4: 1.5952808021 -2.21469988718 -1.98935169586 -0.05380504058 0.5566631987 -1.1293630961 0.02800215878 -0.934097631644 -1.5235668004 0.7002136495 4 5
5: 0.3295077718 1.12493091814 0.61982574789 -1.37705955683 -0.6887556945 1.4330237017 -0.74327320888 -1.253633400239 0.5939461876 1.5868334545 5 6
6: -0.8204683841 -0.04493360902 -0.05612873953 -0.41499456330 -0.7074951570 1.9803998985 0.18879229951 0.291446235517 0.3329503712 0.5584864256 6 7
7: 0.4874290524 -0.01619026310 -0.15579550671 -0.39428995371 0.3645819621 -0.3672214765 -1.80495862889 -0.443291873218 1.0630998373 -1.2765922085 7 8
8: 0.7383247051 0.94383621069 -1.47075238390 -0.05931339671 0.7685329245 -1.0441346263 1.46555486156 0.001105351632 -0.3041839236 -0.5732654142 8 9
9: 0.5757813517 0.82122119510 -0.47815005511 1.10002537198 -0.1123462122 0.5697196274 0.15325333821 0.074341324152 0.3700188099 -1.2246126149 9 10
10: -0.3053883872 0.59390132122 0.41794156020 0.76317574846 0.8811077265 -0.1350546039 2.17261167036 -0.589520946188 0.2670987908 -0.4734006364 10 11
a1 a2
1: 2.401617761 -0.6264538107
2: 1.207867806 -0.7099464309
3: 1.178086997 -0.8356286124
4: 1.595280802 -2.2146998872
5: 1.586833455 -1.3770595568
6: 1.980399899 -0.8204683841
7: 1.063099837 -1.8049586289
8: 1.465554862 -1.4707523839
9: 1.100025372 -1.2246126149
10: 2.172611670 -0.5895209462
EDIT2: Il ressemble sur mes données à l'aide de DT[, (newColnames):=f(.DT), by=IDX, .SDcols=someIdx]
est beaucoup plus lent qu'à l'appliquer de manière, qui est attendu ?
- merci pour votre commentaire, je vais continuer à l'appliquer comme il semble le moyen le plus rapide et de loin, merci pour votre réponse aussi, mais comme je l'ai dit dans le post min et max ne sont que de simples exemple,
apply
permettre beaucoup plus courte et flexible code. À la fin, je suis plus gêné avec ledata.table(matrix(...
partie
Vous devez vous connecter pour publier un commentaire.
La création de
.SD
sur chaque ligne peut être très coûteuse, surtout si vos données.la table se compose derows >> columns
. J'avais des conseils à l'aide depmin
etpmax
à travers les colonnes avec une boucle. Je vais illustrer cela avec un plus grand de données (le long de la lignes).De données:
Fonctions:
Benchmarking:
--
Comme @Frank points dans des commentaires, vous pouvez remplacer la boucle for avec
do.call
comme:colrange = (1:ncol(DT))[grepl('^V[[:digit:]]+$',names(DT))]; DT[,c("min","max"):={z <- "[.listof"(DT,colrange); list(do.call(pmin,z),do.call(pmax,z))}]
. J'ai dû cherchermethods("[")
de comprendre.z <- "[.listof"...
.do.call
s'attend à unlist
etdata.table
est à l'intérieur d'unlist
. Donc, vous pourriez faire:DT[,c("min","max"):= list(do.call(pmin,DT[, 1:10, with=FALSE),do.call(pmax,DT[, 1:10, with=FALSE))]
with=FALSE
.Puisque vous avez déjà les numéros de ligne comme une colonne dans votre
data.table
*, vous pourriez faire:ou
La deuxième option utilise le silencieux par sans par.
*bien sûr, vous pourriez tout aussi bien utiliser
row.names
ou1:nrow(DT)
by=row.names(DT)
et il a eu une erreur. Pour clarifier, il est dit "by=eval(row.names(DT))
devrait fonctionner."by=list(row.names(DT))
cols <- names(DT)[grepl('^V[[:digit:]]$',names(DT))];newcols <- c("min","max");myfun <- range;DT[,(newcols):=as.list(myfun(.SD)),.SDcols=cols,by=1:nrow(DT)]
.1:nrow(DT)
mieux, je vais voler et ajoutez-le au-dessus 🙂Celui-ci énonce les étapes dans le cas où vous souhaitez utiliser une autre fonction:
[[:digit:]]+$
je suppose que sinon, Il va sauter toutes les colonnes avec des chiffres > 9 (V10 par exemple).data.table
avec BEAUCOUP de lignes.data.table
. Je serais intéressé de voir comment il pourrait en être fait.J'ai loupé quelque chose, n'est-ce pas donner la min tout le rang
Méthode 1
Méthode 2