J'ai essayé de trouver une réponse à cette question pendant de nombreux mois tout en apprenant les pandas. J'utilise SAS pour mon travail quotidien et c'est génial pour son support hors cœur. Cependant, SAS est horrible en tant que logiciel pour de nombreuses autres raisons.
Un jour, j'espère remplacer mon utilisation de SAS par python et pandas, mais il me manque actuellement un flux de travail hors cœur pour les grands ensembles de données. Je ne parle pas de "big data" qui nécessite un réseau distribué, mais plutôt de fichiers trop volumineux pour tenir en mémoire mais assez petits pour tenir sur un disque dur.
Ma première pensée est d'utiliser HDFStore
pour conserver de grands ensembles de données sur le disque et extraire uniquement les éléments dont j'ai besoin dans les trames de données pour l'analyse. D'autres ont mentionné MongoDB comme une alternative plus facile à utiliser. Ma question est la suivante:
Quels sont les workflows de bonnes pratiques pour accomplir les tâches suivantes:
- Chargement de fichiers plats dans une structure de base de données permanente sur disque
- Interroger cette base de données pour récupérer des données à alimenter dans une structure de données pandas
- Mise à jour de la base de données après manipulation de pièces dans des pandas
Des exemples concrets seraient très appréciés, en particulier de la part de ceux qui utilisent des pandas sur des "grandes données".
Modifier - un exemple de la façon dont j'aimerais que cela fonctionne:
- Importez de manière itérative un grand fichier plat et stockez-le dans une structure de base de données permanente sur disque. Ces fichiers sont généralement trop volumineux pour tenir en mémoire.
- Afin d'utiliser Pandas, je voudrais lire des sous-ensembles de ces données (généralement seulement quelques colonnes à la fois) qui peuvent tenir en mémoire.
- Je créerais de nouvelles colonnes en effectuant diverses opérations sur les colonnes sélectionnées.
- Je devrais ensuite ajouter ces nouvelles colonnes dans la structure de la base de données.
J'essaie de trouver un moyen pratique d'exécuter ces étapes. En lisant des liens sur les pandas et les pytables, il semble que l'ajout d'une nouvelle colonne pourrait être un problème.
Modifier - Répondre spécifiquement aux questions de Jeff:
- Je construis des modèles de risque de crédit à la consommation. Les types de données comprennent les caractéristiques du téléphone, du SSN et de l'adresse; valeurs des propriétés; des informations désobligeantes comme les casiers judiciaires, les faillites, etc ... Les ensembles de données que j'utilise quotidiennement comportent près de 1 000 à 2 000 champs en moyenne de types de données mixtes: variables continues, nominales et ordinales de données numériques et de caractères. J'ajoute rarement des lignes, mais j'effectue de nombreuses opérations qui créent de nouvelles colonnes.
- Les opérations typiques impliquent la combinaison de plusieurs colonnes utilisant une logique conditionnelle dans une nouvelle colonne composée. Par exemple
if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'
,. Le résultat de ces opérations est une nouvelle colonne pour chaque enregistrement de mon jeu de données. - Enfin, je voudrais ajouter ces nouvelles colonnes dans la structure de données sur disque. Je répéterais l'étape 2, en explorant les données avec des tableaux croisés et des statistiques descriptives en essayant de trouver des relations intéressantes et intuitives à modéliser.
- Un fichier de projet typique fait généralement environ 1 Go. Les fichiers sont organisés de manière à ce qu'une ligne se compose d'un enregistrement de données de consommation. Chaque ligne a le même nombre de colonnes pour chaque enregistrement. Ce sera toujours le cas.
- Il est assez rare que je sous-ensemble de lignes lors de la création d'une nouvelle colonne. Cependant, il est assez courant pour moi de sous-définir des lignes lors de la création de rapports ou de la génération de statistiques descriptives. Par exemple, je souhaiterais peut-être créer une fréquence simple pour un secteur d'activité spécifique, par exemple les cartes de crédit Retail. Pour ce faire, je ne sélectionnerais que les enregistrements pour lesquels le secteur d'activité = vente au détail, en plus des colonnes sur lesquelles je souhaite faire rapport. Cependant, lors de la création de nouvelles colonnes, je tirais toutes les lignes de données et uniquement les colonnes dont j'avais besoin pour les opérations.
- Le processus de modélisation nécessite d'analyser chaque colonne, de rechercher des relations intéressantes avec une variable de résultat et de créer de nouvelles colonnes composées qui décrivent ces relations. Les colonnes que j'explore se font généralement en petits ensembles. Par exemple, je vais me concentrer sur un ensemble de disons 20 colonnes traitant uniquement des valeurs des propriétés et observer comment elles sont liées au défaut de paiement d'un prêt. Une fois que ceux-ci sont explorés et que de nouvelles colonnes sont créées, je passe ensuite à un autre groupe de colonnes, disons l'enseignement collégial, et je répète le processus. Ce que je fais, c'est créer des variables candidates qui expliquent la relation entre mes données et certains résultats. À la toute fin de ce processus, j'applique certaines techniques d'apprentissage qui créent une équation à partir de ces colonnes composées.
Il est rare que j'ajoute des lignes à l'ensemble de données. Je créerai presque toujours de nouvelles colonnes (variables ou fonctionnalités dans le langage statistique / d'apprentissage automatique).
Réponses:
J'utilise régulièrement des dizaines de gigaoctets de données de cette façon, par exemple, j'ai des tables sur le disque que je lis via des requêtes, crée des données et les ajoute.
Il vaut la peine de lire les documents et plus tard dans ce fil pour plusieurs suggestions sur la façon de stocker vos données.
Des détails qui affecteront la façon dont vous stockez vos données, comme:
Donnez autant de détails que possible; et je peux vous aider à développer une structure.
(Donner un exemple de jouet pourrait nous permettre de proposer des recommandations plus spécifiques.)
Solution
Assurez-vous d'avoir au moins des pandas
0.10.1
installés.Lisez les fichiers itératifs morceau par morceau et les requêtes de table multiples .
Étant donné que pytables est optimisé pour fonctionner en ligne (c'est ce sur quoi vous interrogez), nous allons créer une table pour chaque groupe de champs. De cette façon, il est facile de sélectionner un petit groupe de champs (qui fonctionnera avec une grande table, mais c'est plus efficace de le faire de cette façon ... Je pense que je pourrai peut-être corriger cette limitation à l'avenir ... c'est plus intuitif de toute façon):
(Ce qui suit est un pseudocode.)
Lire les fichiers et créer le stockage (essentiellement faire ce qui
append_to_multiple
fait):Maintenant, vous avez toutes les tables dans le fichier (en fait, vous pouvez les stocker dans des fichiers séparés si vous le souhaitez, vous devrez probablement ajouter le nom de fichier à group_map, mais ce n'est probablement pas nécessaire).
Voici comment obtenir des colonnes et en créer de nouvelles:
Lorsque vous êtes prêt pour le post-traitement:
Concernant data_columns, vous n'avez en fait pas besoin de définir ANY data_columns; ils vous permettent de sous-sélectionner des lignes en fonction de la colonne. Par exemple, quelque chose comme:
Ils peuvent être plus intéressants pour vous à l'étape de la génération du rapport final (essentiellement une colonne de données est séparée des autres colonnes, ce qui pourrait avoir un impact sur l'efficacité si vous en définissez beaucoup).
Vous pouvez également vouloir:
Faites-moi savoir quand vous avez des questions!
la source
Je pense que les réponses ci-dessus manquent d'une approche simple que j'ai trouvée très utile.
Lorsque j'ai un fichier trop volumineux pour être chargé en mémoire, je le divise en plusieurs fichiers plus petits (soit par ligne, soit par colonnes)
Exemple: Dans le cas de 30 jours de données de trading d'une taille de ~ 30 Go, je les divise en un fichier par jour de ~ 1 Go. Je traite ensuite chaque fichier séparément et agrège les résultats à la fin
L'un des plus grands avantages est qu'il permet le traitement parallèle des fichiers (soit plusieurs threads ou processus)
L'autre avantage est que la manipulation de fichiers (comme l'ajout / la suppression de dates dans l'exemple) peut être accomplie par des commandes shell régulières, ce qui n'est pas possible dans des formats de fichiers plus avancés / compliqués
Cette approche ne couvre pas tous les scénarios, mais est très utile dans beaucoup d'entre eux
la source
Il y a maintenant, deux ans après la question, un équivalent de pandas «hors du cœur»: dask . C'est excellent! Bien qu'il ne prenne pas en charge toutes les fonctionnalités de pandas, vous pouvez aller très loin avec.
la source
dask
.Si vos jeux de données se situent entre 1 et 20 Go, vous devriez obtenir un poste de travail avec 48 Go de RAM. Les pandas peuvent ensuite conserver l'ensemble de données en RAM. Je sais que ce n'est pas la réponse que vous cherchez ici, mais faire du calcul scientifique sur un ordinateur portable avec 4 Go de RAM n'est pas raisonnable.
la source
Je sais que c'est un vieux fil, mais je pense que la bibliothèque Blaze mérite d'être vérifiée. Il est conçu pour ces types de situations.
De la documentation:
Blaze étend l'utilisabilité de NumPy et Pandas à l'informatique distribuée et hors cœur. Blaze fournit une interface similaire à celle de NumPy ND-Array ou Pandas DataFrame, mais mappe ces interfaces familières sur une variété d'autres moteurs de calcul comme Postgres ou Spark.
Edit: Soit dit en passant, il est soutenu par ContinuumIO et Travis Oliphant, auteur de NumPy.
la source
C'est le cas du pymongo. J'ai également prototypé en utilisant SQL Server, SQLite, HDF, ORM (SQLAlchemy) en Python. Tout d'abord, pymongo est une base de données basée sur des documents, donc chaque personne serait un document (
dict
d'attributs). De nombreuses personnes forment une collection et vous pouvez avoir de nombreuses collections (personnes, bourse, revenus).pd.dateframe -> pymongo Remarque: J'utilise l'
chunksize
inread_csv
pour le garder à 5 à 10k enregistrements (pymongo supprime le socket s'il est plus grand)interrogation: gt = supérieur à ...
.find()
renvoie un itérateur donc j'utilise courammentichunked
pour couper en petits itérateurs.Que diriez-vous d'une jointure puisque j'obtiens normalement 10 sources de données à coller ensemble:
puis (dans mon cas parfois je dois d'abord m'aggraver
aJoinDF
avant son "fusionnable".)Et vous pouvez ensuite écrire les nouvelles informations dans votre collection principale via la méthode de mise à jour ci-dessous. (collection logique vs sources de données physiques).
Pour les recherches plus petites, dénormalisez simplement. Par exemple, vous avez du code dans le document et vous ajoutez simplement le texte du code de champ et effectuez une
dict
recherche lorsque vous créez des documents.Maintenant, vous avez un bel ensemble de données basé sur une personne, vous pouvez libérer votre logique sur chaque cas et créer plus d'attributs. Enfin, vous pouvez lire dans les pandas vos indicateurs clés 3 à mémoire max et faire des pivots / agg / exploration de données. Cela fonctionne pour moi pour 3 millions d'enregistrements avec des nombres / gros texte / catégories / codes / flotteurs / ...
Vous pouvez également utiliser les deux méthodes intégrées à MongoDB (MapReduce et framework d'agrégation). Voir ici pour plus d'informations sur le cadre d'agrégation , car il semble être plus facile que MapReduce et semble pratique pour un travail d'agrégation rapide. Notez que je n'avais pas besoin de définir mes champs ou relations, et je peux ajouter des éléments à un document. À l'état actuel de l'ensemble d'outils numpy, pandas et python qui évolue rapidement, MongoDB m'aide à me mettre au travail :)
la source
In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0
. Des idées qui pourraient être erronées? Mon dataframe se compose de tous les dtypes int64 et est très simple.Je l'ai repéré un peu tard, mais je travaille avec un problème similaire (modèles de remboursement anticipé hypothécaire). Ma solution a été de sauter la couche HDFStore des pandas et d'utiliser des pytables droits. J'enregistre chaque colonne en tant que matrice HDF5 individuelle dans mon fichier final.
Mon flux de travail de base consiste à obtenir d'abord un fichier CSV à partir de la base de données. Je le gzip, donc ce n'est pas aussi énorme. Ensuite, je convertis cela en un fichier HDF5 orienté lignes, en itérant dessus en python, en convertissant chaque ligne en un vrai type de données et en l'écrivant dans un fichier HDF5. Cela prend quelques dizaines de minutes, mais il n'utilise pas de mémoire, car il ne fonctionne que ligne par ligne. Ensuite, je «transpose» le fichier HDF5 orienté lignes en un fichier HDF5 orienté colonnes.
Le tableau transpose ressemble à:
La relire ressemble alors à:
Maintenant, je l'exécute généralement sur une machine avec une tonne de mémoire, donc je ne fais peut-être pas assez attention à mon utilisation de la mémoire. Par exemple, par défaut, l'opération de chargement lit l'ensemble des données.
Cela fonctionne généralement pour moi, mais c'est un peu maladroit, et je ne peux pas utiliser la magie des pytables fantaisistes.
Edit: Le véritable avantage de cette approche, par rapport au tableau des enregistrements pytables par défaut, est que je peux ensuite charger les données dans R en utilisant h5r, qui ne peut pas gérer les tables. Ou, au moins, je n'ai pas pu l'obtenir pour charger des tables hétérogènes.
la source
Une astuce que j'ai trouvée utile pour les cas d'utilisation de données volumineuses consiste à réduire le volume des données en réduisant la précision du flottant à 32 bits. Ce n'est pas applicable dans tous les cas, mais dans de nombreuses applications, la précision 64 bits est excessive et les économies de mémoire 2x en valent la peine. Pour rendre un point évident encore plus évident:
la source
Comme indiqué par d'autres, après quelques années, un équivalent de pandas `` hors du cœur '' a émergé: dask . Bien que dask ne remplace pas les pandas et toutes ses fonctionnalités, il se démarque pour plusieurs raisons:
Dask est une bibliothèque informatique parallèle flexible pour l'informatique analytique qui est optimisée pour la planification dynamique des tâches pour les charges de travail de calcul interactives des collections de «Big Data» comme les tableaux parallèles, les trames de données et les listes qui étendent les interfaces communes comme NumPy, Pandas ou Python aux plus grands itérateurs. que la mémoire ou les environnements distribués et évolue des ordinateurs portables aux clusters.
et pour ajouter un exemple de code simple:
remplace un code pandas comme celui-ci:
et, particulièrement remarquable, fournit à travers l'
concurrent.futures
interface une infrastructure générale pour la soumission de tâches personnalisées:la source
Il convient également de mentionner ici Ray ,
c'est un cadre de calcul distribué, qui a sa propre implémentation pour les pandas de manière distribuée.
Remplacez simplement l'importation des pandas et le code devrait fonctionner tel quel:
pouvez lire plus de détails ici:
https://rise.cs.berkeley.edu/blog/pandas-on-ray/
la source
Encore une variation
De nombreuses opérations effectuées dans les pandas peuvent également être effectuées sous forme de requête db (sql, mongo)
L'utilisation d'un SGBDR ou d'un mongodb vous permet d'effectuer certaines des agrégations dans la requête DB (qui est optimisée pour les données volumineuses et utilise efficacement le cache et les index)
Plus tard, vous pouvez effectuer un post-traitement à l'aide de pandas.
L'avantage de cette méthode est que vous obtenez les optimisations de base de données pour travailler avec des données volumineuses, tout en définissant la logique dans une syntaxe déclarative de haut niveau - et sans avoir à vous occuper des détails de décider quoi faire en mémoire et que faire du noyau.
Et bien que le langage de requête et les pandas soient différents, il n'est généralement pas compliqué de traduire une partie de la logique de l'un à l'autre.
la source
Considérez Ruffus si vous choisissez le chemin simple de création d'un pipeline de données divisé en plusieurs fichiers plus petits.
la source
J'ai récemment rencontré un problème similaire. J'ai trouvé que lire simplement les données en morceaux et les ajouter pendant que je les écris en morceaux sur le même csv fonctionne bien. Mon problème était l'ajout d'une colonne de date basée sur les informations d'une autre table, en utilisant la valeur de certaines colonnes comme suit. Cela peut aider ceux qui sont confus par dask et hdf5 mais plus familiers avec des pandas comme moi.
la source
Je voudrais souligner le package Vaex.
Jetez un œil à la documentation: https://vaex.readthedocs.io/en/latest/ L'API est très proche de l'API des pandas.
la source
Pourquoi les pandas? Avez-vous essayé Standard Python ?
L'utilisation de la bibliothèque standard python. Les pandas sont soumis à des mises à jour fréquentes, même avec la sortie récente de la version stable.
En utilisant la bibliothèque Python standard, votre code s'exécutera toujours.
Une façon de le faire est d'avoir une idée de la façon dont vous souhaitez que vos données soient stockées et des questions que vous souhaitez résoudre concernant les données. Ensuite, dessinez un schéma de la façon dont vous pouvez organiser vos données (tableaux de réflexion) qui vous aidera à interroger les données, pas nécessairement la normalisation.
Vous pouvez faire bon usage de:
Ram et HDD devient de moins en moins cher avec le temps et le python 3 standard est largement disponible et stable.
la source
En ce moment, je travaille "comme" vous, juste à une échelle inférieure, c'est pourquoi je n'ai pas de PoC pour ma suggestion.
Cependant, il semble que je réussisse à utiliser le cornichon comme système de mise en cache et à externaliser l'exécution de diverses fonctions dans des fichiers - en exécutant ces fichiers à partir de mon fichier commando / principal; Par exemple, j'utilise un prepare_use.py pour convertir les types d'objets, diviser un ensemble de données en ensemble de données de test, de validation et de prédiction.
Comment fonctionne votre mise en cache avec des cornichons? J'utilise des chaînes afin d'accéder aux fichiers de pickle qui sont créés dynamiquement, en fonction des paramètres et des ensembles de données qui ont été passés (avec cela j'essaie de capturer et de déterminer si le programme a déjà été exécuté, en utilisant .shape pour l'ensemble de données, dict pour passé paramètres). En respectant ces mesures, j'obtiens une chaîne pour essayer de trouver et de lire un fichier .pickle et peut, s'il est trouvé, sauter le temps de traitement afin de passer à l'exécution sur laquelle je travaille en ce moment.
En utilisant des bases de données, j'ai rencontré des problèmes similaires, c'est pourquoi j'ai trouvé la joie d'utiliser cette solution, cependant - il y a certainement de nombreuses contraintes - par exemple, stocker d'énormes jeux de cornichons en raison de la redondance. La mise à jour d'une table d'avant en après une transformation peut se faire avec une indexation appropriée - la validation des informations ouvre un tout autre livre (j'ai essayé de consolider les données de loyer analysées et j'ai cessé d'utiliser une base de données après 2 heures essentiellement - comme j'aurais aimé revenir en arrière après chaque processus de transformation)
J'espère que mes 2 cents vous aideront d'une manière ou d'une autre.
Salutations.
la source