J'ai de très grandes tables (30 millions de lignes) que je voudrais charger car les trames de données dans R. read.table()
ont beaucoup de fonctionnalités pratiques, mais il semble qu'il y ait beaucoup de logique dans l'implémentation qui ralentirait les choses. Dans mon cas, je suppose que je connais les types de colonnes à l'avance, le tableau ne contient aucun en-tête de colonne ou nom de ligne et n'a pas de caractères pathologiques dont je dois m'inquiéter.
Je sais que la lecture dans un tableau sous forme de liste scan()
peut être assez rapide, par exemple:
datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))
Mais certaines de mes tentatives pour convertir cela en une trame de données semblent réduire les performances de ce qui précède d'un facteur 6:
df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))
Existe-t-il une meilleure façon de le faire? Ou peut-être une approche complètement différente du problème?
feather
. Pour la lecture des donnéesfeather
est beaucoup plus rapide quefread
. Par exemple, sur un ensemble de données de 4 Go que je viens de chargerread_feather
était environ 4,5 fois plus rapide quefread
. Pour l'enregistrement des donnéesfwrite
est encore plus rapide. blog.dominodatalab.com/the-r-data-io-shootoutfeather
est donc plus rapide pour la lecture, mais il utilise beaucoup plus d'espace de stockage.feather
c'est une bonne option. Si vous ne souhaitez que lire vos données en R, ilrds
est préférable.Voici un exemple qui utilise
fread
dedata.table
1.8.7Les exemples viennent de la page d'aide de
fread
, avec les timings sur mon windows XP Core 2 duo E8400.table de lecture standard
table de lecture optimisée
effrayer
sqldf
ff / ffdf
En résumé:
la source
fread
. J'avais essayé de le lire avec les fonctions de base R et cela a pris environ 15 heures.readr
?fread
a maintenant de vrais concurrents, il pourrait être utile d'ajouter des repères pour unefread
utilisation optimisée - en spécifiantcolClasses
, etc.Je n'ai pas vu cette question au départ et posé une question similaire quelques jours plus tard. Je vais reprendre ma question précédente, mais j'ai pensé ajouter une réponse ici pour expliquer comment je faisais
sqldf()
cela.Il y a eu peu de discussions sur la meilleure façon d'importer 2 Go ou plus de données texte dans un bloc de données R. Hier, j'ai écrit un article de blog sur l'utilisation
sqldf()
de l'importation de données dans SQLite en tant que zone de transit, puis sur l'aspiration de SQLite dans R. Cela fonctionne très bien pour moi. J'ai pu extraire 2 Go (3 colonnes, lignes de 40 mm) de données en moins de 5 minutes. En revanche, laread.csv
commande a fonctionné toute la nuit et n'a jamais abouti.Voici mon code de test:
Configurez les données de test:
J'ai redémarré R avant d'exécuter la routine d'importation suivante:
J'ai laissé la ligne suivante fonctionner toute la nuit mais elle ne s'est jamais terminée:
la source
Étrangement, personne n'a répondu à la partie inférieure de la question pendant des années, même s'il s'agit d'une question importante - ce
data.frame
sont simplement des listes avec les bons attributs, donc si vous avez de grandes données, vous ne voulez pas les utiliseras.data.frame
ou similaires pour une liste. Il est beaucoup plus rapide de simplement "transformer" une liste en un bloc de données sur place:Cela ne fait aucune copie des données, c'est donc immédiat (contrairement à toutes les autres méthodes). Il suppose que vous avez déjà défini
names()
la liste en conséquence.[Quant au chargement de grandes données dans R - personnellement, je les vide par colonne dans des fichiers binaires et les utilise
readBin()
- qui est de loin la méthode la plus rapide (autre que le mmapping) et n'est limitée que par la vitesse du disque. L'analyse des fichiers ASCII est intrinsèquement lente (même en C) par rapport aux données binaires.]la source
tracmem
suggère celaattr<-
etclass<-
faites des copies en interne.bit::setattr
oudata.table::setattr
pas.df=scan(...); names(df)=...; attr...; class...
- voirtracemem()
(testé dans R 2.15.2)Cela a déjà été demandé sur R-Help , donc cela vaut la peine d'être examiné.
Une suggestion était d'utiliser
readChar()
puis de manipuler les chaînes sur le résultat avecstrsplit()
etsubstr()
. Vous pouvez voir que la logique impliquée dans readChar est bien inférieure à read.table.Je ne sais pas si la mémoire est un problème ici, mais vous voudrez peut-être également jeter un œil au package HadoopStreaming . Cela utilise Hadoop , qui est un cadre MapReduce conçu pour traiter des ensembles de données volumineux. Pour cela, vous utiliseriez la fonction hsTableReader. Ceci est un exemple (mais il a une courbe d'apprentissage pour apprendre Hadoop):
L'idée de base ici est de diviser l'importation de données en morceaux. Vous pouvez même aller jusqu'à utiliser l'un des frameworks parallèles (par exemple snow) et exécuter l'importation de données en parallèle en segmentant le fichier, mais très probablement pour les grands ensembles de données qui ne vous aideront pas car vous rencontrerez des contraintes de mémoire, c'est pourquoi map-Reduce est une meilleure approche.
la source
Une alternative consiste à utiliser le
vroom
package. Maintenant sur CRAN.vroom
ne charge pas l'intégralité du fichier, il indexe l'emplacement de chaque enregistrement et est lu plus tard lorsque vous l'utilisez.Voir Introduction à vroom , Premiers pas avec vroom et les références de vroom .
L'aperçu de base est que la lecture initiale d'un fichier volumineux sera beaucoup plus rapide et que les modifications ultérieures des données peuvent être légèrement plus lentes. Selon votre utilisation, cela pourrait donc être la meilleure option.
Voir un exemple simplifié des références Vroom ci-dessous, les éléments clés à voir sont les temps de lecture super rapides, mais les opérations légèrement semées comme l'agrégat, etc.
la source
Quelques points supplémentaires mineurs qui méritent d'être mentionnés. Si vous avez un très gros fichier, vous pouvez calculer à la volée le nombre de lignes (si aucun en-tête) en utilisant (où
bedGraph
est le nom de votre fichier dans votre répertoire de travail):Vous pouvez ensuite l'utiliser soit dans
read.csv
,read.table
...la source
Souvent, je pense que c'est juste une bonne pratique de garder de plus grandes bases de données à l'intérieur d'une base de données (par exemple Postgres). Je n'utilise rien de trop grand que (nrow * ncol) ncell = 10M, ce qui est assez petit; mais je trouve souvent que je veux que R crée et conserve des graphiques gourmands en mémoire uniquement pendant que je recherche à partir de plusieurs bases de données. À l'avenir des ordinateurs portables de 32 Go, certains de ces types de problèmes de mémoire disparaîtront. Mais l'attrait d'utiliser une base de données pour conserver les données, puis d'utiliser la mémoire de R pour les résultats de requête et les graphiques résultants peut toujours être utile. Quelques avantages:
(1) Les données restent chargées dans votre base de données. Vous vous reconnectez simplement dans pgadmin aux bases de données que vous souhaitez lorsque vous rallumez votre ordinateur portable.
(2) Il est vrai que R peut effectuer des opérations statistiques et graphiques beaucoup plus astucieuses que SQL. Mais je pense que SQL est mieux conçu pour interroger de grandes quantités de données que R.
la source
Je lis les données très rapidement en utilisant le nouveau
arrow
package. Il semble être à un stade assez précoce.Plus précisément, j'utilise le format colonnaire parquet . Cela se reconvertit en un
data.frame
dans R, mais vous pouvez obtenir des accélérations encore plus profondes si vous ne le faites pas. Ce format est pratique car il peut également être utilisé à partir de Python.Mon cas d'utilisation principal pour cela est sur un serveur RShiny assez restreint. Pour ces raisons, je préfère garder les données attachées aux applications (c'est-à-dire en dehors de SQL), et donc nécessiter une petite taille de fichier ainsi qu'une vitesse.
Cet article lié fournit une analyse comparative et un bon aperçu. J'ai cité quelques points intéressants ci-dessous.
https://ursalabs.org/blog/2019-10-columnar-perf/
Taille du fichier
Vitesse de lecture
Test indépendant
J'ai effectué une analyse comparative indépendante sur un ensemble de données simulées de 1 000 000 de lignes. Fondamentalement, j'ai mélangé un tas de choses pour tenter de contester la compression. J'ai également ajouté un court champ de texte de mots aléatoires et deux facteurs simulés.
Les données
Lire et écrire
L'écriture des données est facile.
La lecture des données est également facile.
J'ai testé la lecture de ces données par rapport à quelques-unes des options concurrentes et j'ai obtenu des résultats légèrement différents de ceux de l'article ci-dessus, ce qui est attendu.
Ce fichier est loin d'être aussi volumineux que l'article de référence, alors c'est peut-être la différence.
Les tests
as_data_frame = FALSE
)arrow
)feather
)Observations
Pour ce fichier particulier,
fread
est en fait très rapide. J'aime la petite taille du fichier duparquet2
test hautement compressé . Je peux investir du temps pour travailler avec le format de données natif plutôt quedata.frame
si j'ai vraiment besoin d'accélérer.Voici
fst
également un excellent choix. J'utiliserais soit lefst
format hautement compressé , soit le format hautement compressé,parquet
selon que j'aurais besoin d'un compromis entre la vitesse ou la taille du fichier.la source
Au lieu de la table de lecture conventionnelle, je pense que la peur est une fonction plus rapide. La spécification d'attributs supplémentaires, comme sélectionner uniquement les colonnes requises, la spécification des colclasses et de la chaîne comme facteurs réduira le temps nécessaire pour importer le fichier.
la source
J'ai tout essayé ci-dessus et [readr] [1] a fait le meilleur travail. Je n'ai que 8 Go de RAM
Boucle pour 20 fichiers, 5 Go chacun, 7 colonnes:
la source