1
votes

Comment puis-je mélanger les lignes d'un gros fichier csv et écrire le résultat dans un nouveau fichier csv sans utiliser trop de mémoire?

Donc, si j'ai un fichier csv comme suit:

User  Gender
 C    F
 A    M
 B    F

Alors je veux écrire un autre fichier csv avec des lignes mélangées comme ceci (à titre d'exemple):

User  Gender
 A    M
 B    F
 C    F

Mon problème est que je ne sais pas comment sélectionner des lignes au hasard et m'assurer que j'obtiens chaque ligne du fichier csv d'origine. Pour référence, mon fichier csv est d'environ 3 Go. Si je charge tout mon ensemble de données dans une trame de données et que j'utilise le package aléatoire pour le mélanger, mon PC se bloque en raison de l'utilisation de la RAM.


0 commentaires

3 Réponses :


2
votes

Le plus simple (et le plus rapide) est probablement d'utiliser shuf dans bash!

import sh
sh.shuf("words.txt", out="shuffled_words.txt")

(je sais que vous avez demandé une solution Python, mais je vais supposons que c'est toujours une meilleure réponse)

Pour le faire par programmation à partir de Python:

shuf words.txt > shuffled_words.txt


4 commentaires

Que fait exactement sh.shuf? Je n'arrive pas à trouver de documentation à ce sujet.


@mrnovice sh est juste un wrapper autour des commandes bash. Donc tout ce qui vient après sh. sera une commande bash shell.


J'ai essayé de l'utiliser, mais j'ai eu une erreur disant que sh n'est pris en charge que sur mac et linux (j'utilise Windows)


@PascalVKooten et si mon CSV a un en-tête et que je ne veux pas que l'en-tête soit mélangé?



0
votes
  • Créez un tableau de lignes au début des positions de fichier, en lisant le fichier une fois en tant que fichier à accès aléatoire ou mappé en mémoire. Le tableau a une entrée supplémentaire avec la longueur du fichier, donc la ligne i contient les octets [array [i], array [i + 1]> .
  • Mélangez les indices 0 .. nombre de lignes - 1.
  • Vous pouvez désormais utiliser le positionnement à accès aléatoire (recherche) pour lire un tampon de ligne.

2 commentaires

Supposons que mon fichier csv contienne 1000 lignes (hors en-tête). Ensuite, ce tableau que vous mentionnez stockerait les nombres 1 à 1000 et il y aurait une entrée supplémentaire avec le nombre 1000 à la fin. Ensuite, je mélange ce tableau, en excluant la dernière entrée. Est-ce correct jusqu'à présent? Je ne comprends pas vraiment ce que vous entendez par positionnement à accès aléatoire.


Non, vous avez besoin d'un tableau de permutation stockant les indices 1 à 1000 mélangés (ou 0 à 999 si les indices basés sur zéro). Pseudo code: pour j entre 1 et 1000, i = permutation [j]; ligne de sortie (i)



0
votes

Vous pouvez utiliser l'argument chunk_size pour csv dans des morceaux

df_chunks = pandas.read_csv ("your_csv_name.csv", chunk_size = 10)

Ensuite, vous pouvez mélanger seulement les morceaux, donc cela prend moins de mémoire

new_df = pandas.concat(new_chunks)
new_df.to_csv("your_new_csv_name.csv")

Ensuite, vous pouvez les concater et les enregistrer dans un autre csv:

for chunk in df_chunks:
    do stuff

Si vous avez un problème de mémoire, pendant que vous créez new_chunks, n'oubliez pas d'effacer l'ancien car vous ne voulez pas qu'ils restent dans la RAM sans raison, vous pouvez le faire avec chunk=None


1 commentaires

Je ne pense pas que cette solution fonctionnerait pour mon ensemble de données, car il existe deux catégories de données, l'une dans la moitié supérieure du fichier, la seconde dans la moitié inférieure. Donc, cette méthode ne ferait pas correctement passer les deux catégories. Excusez-moi, j'aurais probablement dû inclure cette information dans ma question.