7
votes

Sous-formulation rapide dans R

J'ai un dataframe dat de taille 30000 x 50. J'ai également une liste distincte contenant des points aux groupements de lignes de ce fichier de données, par exemple,

> system.time(lapply(rows, function(r) {dat[r, ]}))
   user  system elapsed 
 246.09    0.01  247.23 


2 commentaires

Pourriez-vous donner à peu près combien d'éléments dans rangs et à peu près combien d'éléments dans lignes [[i]] ? De plus, vos royaux sont tous uniques, non? (J'ai fait un dat aléatoire , 30000x50, mais je semble avoir des temps rapides pour les lignes i maquillage - ils ne sont probablement pas assez gros?)


lignes a environ 15 000 éléments; Longueur (lignes [[[I]]) varie de 1 à 50


5 Réponses :


1
votes

Je suis d'accord avec le café mathématique que je reçois aussi des temps rapides pour cela.

Je ne sais pas si c'est possible, mais par cassette comme un vecteur puis convertir en numérique, vous pouvez obtenir un boost de vitesse. < Pré> xxx

edit: xxx


3 commentaires

Cependant, les lignes sont des noms de lignes non des indices de ligne, donc as.numérique entraînera l'extraction des mauvaises lignes.


Les noms de ligne pourraient-ils être convertis en vecteurs de caractère numériques ou en nombre? S'ils sont des vecteurs de caractères, je vous suggère de créer une autre variable / colonne et d'avoir des noms de rangée numérique. Cela vous donne des royaux numériques et conserve vos informations. Je vais démontrer.


Ouais, je reçois le problème du personnage Remises maintenant. Il est possible qu'une table de hachage puisse être utilisée ici, mais j'aimerais que les solutions du café dri et mathématique bordaient d'abord.



2
votes

Vous pouvez essayer cette modification: xxx


2 commentaires

Celui-ci a absolument tué mon ordinateur - je pense dat [rownames (dat)% en% R,] est plus lent que dat [r,]


Ouais. Celui-ci double double le temps requis. Mais merci pour votre suggestion.



4
votes

Voici une tentative d'accélération - il dépend du fait qu'il est plus rapide de rechercher un indice de rangée que de rechercher un nom de ligne, et essaie ainsi de faire une cartographie de la rive-numéros dans DAT .piedsp>First crée des données de la même taille que le vôtre et attribuez des royales numériques: p>

map <- rep(-1,max(as.numeric(rownames(dat))))
obj <- sort(as.numeric(rownames(dat)), index.return=T)
map[obj$x] <- obj$ix


0 commentaires

5
votes

Mise à jour

Mon message original a commencé avec cette déclaration erronée: P>

Le problème avec indexation via rownames code> et colnames code> est-ce que vous Exécutez une analyse vectorielle / linéaire pour chaque élément, par exemple. Vous chassez à travers chaque ligne à voir laquelle s'appelle "36", puis à partir de la Commencer à recommencer pour "34". P> BlockQuote>

Simon a souligné dans les commentaires ici que r utilise apparemment une table de hachage pour l'indexation. Désolé pour l'erreur. P>

Réponse originale H2>

Notez que les suggestions de cette réponse supposent que vous avez des sous-ensembles de données non superposés. EM> P>

Si vous souhaitez conserver votre stratégie de recherche de liste, je vous suggère de stocker les indices de la ligne réelle au sujet des noms de chaîne. P>

Une alternative consiste à stocker vos informations "Groupe" comme une autre colonne à Votre data.frame code>, puis divisé code> votre data.frame code> sur son groupe, par exemple. Disons votre data.frame recodé. / code> ressemble à ceci: p> xxx pré>

vous pouvez alors faire: p> xxx pré>

ou, en fonction de ce que vous voulez vraiment faire avec vos "scissions", vous pouvez convertir votre data.frame code> en un data.able code> et définissez sa clé sur votre nouveau code> colonne code> : p> xxx pré>

faire votre liste de liste - qui vous donnera le même résultat que le divisé code> ci-dessus p> xxx

mais vous voulez probablement "travailler sur vos crits", et vous pouvez le faire en ligne, par exemple: p> xxx pré>

vous pouvez faire la dernière étape de " Une mode similaire "avec Plyr code> , EG: P>

library(plyr)
ddply(dat, "group", summarize, nrow=length(a), mean.a=mean(a),
      mean.b=mean(b))
  group nrow mean.a     mean.b
1     a    2   64.0 -0.7141803
2     b    5   62.2 -0.3006076
3     c    3   60.0  0.1240660


2 commentaires

"Le problème avec l'indexation via Rownames et Colnames est que vous exécutez une analyse vectorielle / linéaire pour chaque élément" - est un problème clair, r n'est pas si stupide - il utilise des tables de hasch pour l'indexation. Cependant, étant donné que la correspondance partielle est la valeur par défaut que vous pouvez faire mieux en utilisant correspondant pour éviter cela (ou de préférence FastMatch car vous souhaitez réutiliser la table de hachage) - Pour des exemples, j'ai ajouté une réponse.


@Stevelianoglou, malgré l'erreur sur le commentaire de l'analyse linéaire, merci de démontrer l'utilisation de Split .



18
votes

L'un des problèmes principaux est la correspondance des noms de lignes - la valeur par défaut dans [. data.frame est une correspondance partielle des noms de lignes et vous ne le souhaitez probablement pas. mieux avec match . Pour accélérer encore plus loin, vous pouvez utiliser fmatch à partir de FastMatch si vous voulez. Ceci est une modification mineure avec un peu de vitesse: xxx

Vous pouvez obtenir une accélération supplémentaire en utilisant [ (il est lent pour les cadres de données) mais la fractionnement du cadre de données) (Utilisation de Split ) Si votre Les lignes ne se chevauchent pas et couvrent toutes les lignes (et vous pouvez ainsi mapper chaque ligne d'une entrée dans des rangées).

En fonction de vos données réelles, vous risquez peut-être mieux avec des matrices qui ont de loin des opérateurs de sous-totalement plus rapides car ils sont indigènes.


5 commentaires

Fmatch est vraiment assez magique. Je vois maintenant ces timings (comparer à ceux de la question): Système utilisateur écoulé 11,48 0,02 11,64


... Mais FMatch ne gère pas les mises à jour de la table arg: s <- 'a'; fmatch ('a', s); s [1] <- "B ' ; Fmatch ('A', S) La deuxième fois, FMatch ne doit pas trouver de match, mais elle ... En général, il semble dangereux de changer d'objet nommé, et de compter sur ce qu'ils ne sont jamais modifié à nouveau ...


Oui, et les documents avertissent à ce sujet. C'est le prix que vous payez à la vitesse;) Malheureusement, il n'y a aucun moyen de vous être informé de la mise à jour. Et le problème n'est pas nommé du tout sauf le fait que r va heureusement copier l'attribut sur un nouvel objet.


En fait, j'ai trouvé un moyen d'identifier le cas que vous avez illustré (en stockant l'objet parent dans le HASH), la prochaine version de FastMatch devrait pouvoir détecter des attributs copiés hors synchronisation. Merci pour l'exemple :).


Génial que vous pourriez aborder cette affaire. Et la question nommée est que vous «enfreignez les règles» en modifiant un objet nommé en attribuant un nouvel attribut à celui-ci. Les avantages l'emportent peut-être les risques dans votre cas. Une solution aboutissante serait un peu plus encombrante à utiliser: m <- fmakemap (table); fmatch (x, m)