Je suis un peu d'un R hack, mais je suis un empiriste donc, je vais partager quelques choses que j'ai observées et que ceux avec une plus grande compréhension théorique de R faire la lumière sur les "pourquois".
R semble beaucoup plus lentement, en utilisant la norme
les flux de Perl. Depuis stdin et
stout sont beaucoup plus couramment utilisés dans
Perl je suppose qu'il a des optimisations
autour de la façon dont il le fait ces choses. Donc, en R I
trouver BEAUCOUP plus rapide à lire/écrire du texte en utilisant le construit en
les fonctions e.g write.table
).
Comme d'autres l'ont dit, vecteur
les opérations dans R sont plus rapides que
boucles... et w.r.t. la vitesse, la plupart s'appliquent() de la famille
la syntaxe est simplement une jolie wrapper sur
une boucle.
Indexé les choses fonctionnent plus rapidement que
non indexés. (Évident, je sais). Les données.tableau package prend en charge l'indexation de la trame de données de type objets.
Je n'ai jamais utilisé de hachage
les environnements comme @Allen illustré (et je n'ai jamais inhalé de hachage... aussi loin que vous le savez)
Certains de la syntaxe que vous avez utilisé fonctionne, mais pourrait être renforcé. Je ne pense pas que tout cela est vraiment important pour la vitesse, mais le code est un peu plus lisible. Je n'écris pas très serré code, mais j'ai modifié un peu l'évolution des choses comme floor(1000*runif(1))
de sample(1:1000, n, replace=T)
. Je ne veux pas être pédant, j'ai juste écrit de la façon que je le ferais à partir de zéro.
Donc, avec cela à l'esprit, j'ai décidé de tester la valeur de hachage de l'approche que @allen utilisé (parce que c'est nouveau pour moi) sur mon "pauvre homme de hachage" que j'ai créé à l'aide d'une des données indexées.le tableau comme un tableau de recherche. Je ne suis pas sûr à 100% que ce que @allen et moi sommes en train de faire est exactement ce que vous avez fait en Perl parce que mon Perl est assez rouillé. Mais je pense que les deux méthodes ci-dessous faire la même chose. Nous avons tous les deux de l'échantillon de la deuxième jeu de clés à partir des touches dans le "hachage", car cela empêche de hachage manque. Vous voulez tester la façon dont ces exemples poignée de hachage dupes que je n'ai pas donné beaucoup de pensée.
require(data.table)
dtTest <- function(n) {
makeDraw <- function(x) paste(sample(letters, 3, replace=T), collapse="")
key <- sapply(1:n, makeDraw)
value <- sample(1:1000, n, replace=T)
myDataTable <- data.table(key, value, key='key')
newKeys <- sample(as.character(myDataTable$key), n, replace = TRUE)
lookupValues <- myDataTable[newKeys]
strings <- paste("key", lookupValues$key, "Lookup", lookupValues$value )
write.table(strings, file="tmpout", quote=F, row.names=F, col.names=F )
}
#
hashTest <- function(n) {
testHash <- new.env(hash = TRUE, size = n)
for(i in 1:n) {
key <- paste(sample(letters, 3, replace = TRUE), collapse = "")
assign(key, floor(1000*runif(1)), envir = testHash)
}
keyArray <- ls(envir = testHash)
keyLen <- length(keyArray)
keys <- sample(ls(envir = testHash), n, replace = TRUE)
vals <- mget(keys, envir = testHash)
strings <- paste("key", keys, "Lookup", vals )
write.table(strings, file="tmpout", quote=F, row.names=F, col.names=F )
}
si j'ai l'exécution de chaque méthode à l'aide de 100 000 tirages, j'obtiens quelque chose comme ceci:
> system.time( dtTest(1e5))
user system elapsed
2.750 0.030 2.881
> system.time(hashTest(1e5))
user system elapsed
3.670 0.030 3.861
Gardez à l'esprit que c'est toujours beaucoup plus lent que le code Perl qui, sur mon PC, le PC semble fonctionner 100K échantillons en moins d'une seconde.
J'espère que l'exemple ci-dessus aide. Et si vous avez des questions quant à l' why
peut-être @allen, @vince, et @dirk sera en mesure de répondre ;)
Après j'ai tapé ci-dessus, j'ai réalisé que je n'avais pas testé ce que @jean l'a fait. Donc, ce que l'enfer, nous allons faire tous les 3. J'ai changé le code de @john à l'utilisation de l'écriture.tableau() et voici son code:
johnsCode <- function(n){
keys = sapply(character(n), function(x) paste(letters[ceiling(26*runif(3))],
collapse=''))
value <- floor(1000*runif(n))
testHash <- as.list(value)
names(testHash) <- keys
keys <- names(testHash)[ceiling(n*runif(n))]
lookupValue = testHash[keys]
strings <- paste("key", keys, "Lookup", lookupValue )
write.table(strings, file="tmpout", quote=F, row.names=F, col.names=F )
}
et le moment de l'exécution:
> system.time(johnsCode(1e5))
user system elapsed
2.440 0.040 2.544
Et là vous l'avez. @jean écrit serré rapide/R code!