2017-07-12 1 views
2

J'ai un fichier .gz plus gros (2.1G) que j'essaye de charger dans R, mais il est assez grand pour que je le divise en morceaux et charge chacun individuellement avant de les recombiner . Cependant, j'ai de la difficulté à scinder le fichier d'une manière qui préserve la structure des données. Le fichier lui-même, à l'exception des deux premières lignes, est une matrice 56318 x 9592 avec des entrées non homogènes. J'utilise Ubuntu 16.04. Tout d'abord, j'ai essayé d'utiliser la commande Fractionner du terminal comme suggéré par ce lien (https://askubuntu.com/questions/54579/how-to-split-larger-files-into-smaller-parts?rq=1)Diviser les gros fichiers gz tout en préservant les lignes

$ split --lines=10000 "originalFile.gct.gz" "originalFile.gct.gz.part-" 

Faire cela, cependant, crée des fichiers beaucoup plus que je ne l'aurais attendu (depuis ma matrice a 57000 lignes, j'espérais pour produire 6 fichiers, chaque 10000 lignes de taille). En lisant l'une d'entre elles dans R et en examinant les dimensions, je vois que chacune est une matrice de 62x9592, indiquant que toutes les colonnes ont été conservées, mais je reçois beaucoup moins de lignes que j'aurais espéré. De plus, en le lisant, j'obtiens une erreur spécifiant une fin de fichier inattendue. Ma pensée est que ce n'est pas lire comme je le veux.

J'ai trouvé deux alternatives possibles ici - https://superuser.com/questions/381394/unix-split-a-huge-gz-file-by-line

En particulier, j'ai essayé différents arguments en utilisant la tuyauterie gunzip et passer ensuite la sortie par de partager (avec l'hypothèse que peut-être le fichier en cours de compression est ce que conduit à des fins incohérentes). J'ai essayé

$ zcat originalFile.gct.gz | split -l 10000 "originalFile.gct.gz" "originalFile.gct.gz.part-" 

mais, ce faisant, je me suis retrouvé avec exactement les mêmes divisions que j'avais précédemment. J'ai le même problème en remplaçant "zcat" par "gunzip -c", qui aurait dû envoyer la sortie non compressée à la commande split.

Une autre réponse sur ce lien suggéré à la tuyauterie tête ou de queue avec quelque chose comme zcat, par exemple

$ zcat originalFile.gct.gz | head -n 10000 >> "originalFile.gct.gz.1" 

Avec zcat, cela fonctionne parfaitement, et il est exactement ce que je veux. La dimension pour cela finit par être 10000x9592, c'est donc la solution idéale. Une chose que je noterai est que cette sortie est un fichier texte ASCII plutôt qu'un fichier compressé, et je suis parfaitement d'accord avec cela.

Cependant, je veux être en mesure de le faire jusqu'à la fin du fichier, en créant un fichier de sortie supplémentaire pour chaque 10000 lignes. Pour ce cas particulier, ce n'est pas une grosse affaire de faire les six, mais j'ai des dizaines de fichiers comme celui-ci, dont certains sont> 10Go. Ma question, alors, est comment puis-je utiliser la commande fractionnée qui prendra les premières 10000 lignes du fichier décompressé, puis les sortir, mettant automatiquement à jour le suffixe avec chaque nouveau fichier? Fondamentalement, je veux la sortie que j'ai obtenue en utilisant "tête", mais avec "split" afin que je puisse le faire sur l'ensemble du fichier.

+0

Lorsqu'un fichier est compressé, la structure d'origine des données n'est pas visible du tout. Vous devez diviser le fichier avant de le compresser si vous voulez qu'il soit divisé logiquement par les données. – Barmar

+0

@Barmar le problème ici est que j'ai reçu ces fichiers déjà compressés. J'espère les décompresser (sans changer le fichier original) et ensuite diviser cette sortie plutôt que l'inverse – cnolte

+0

votre première commande était fondamentalement en éliminant la sortie de zcat, et split lisait les données compressées directement à partir du fichier. Dans votre solution '-' signifie" lire à partir de l'entrée standard ", alors maintenant diviser lirait les données écrites dans le tuyau par zcat .... –

Répondre

1

Voici la solution qui a fini par travailler pour moi

$ zcat originalFile.gct.gz | split -l 10000 - "originalFile.gtc.gz-" 

Comme Guido mentionné dans le commentaire, ma commande originale

$ zcat originalFile.gct.gz | split -l 10000 "originalFile.gct.gz" "originalFile.gct.gz.part-" 

écartait la sortie de zcat et Split a été une nouvelle fois lire à partir des données compressées. En incluant le "-" après l'argument split, j'ai pu passer la sortie standard de zcat en split, et maintenant la tuyauterie fonctionne comme je m'y attendais.

0

Lorsque vous souhaitez mieux contrôler votre fractionnement, vous pouvez utiliser awk. Vous avez mentionné que les deux premières rangées étaient spéciales. Essayez quelque chose comme

zcat originalFile.gct.gz | 
    awk 'BEGIN {j=1} NR<3 {next} {i++} i%5==0 {j++} {print > "originalFile.gct.part"j }' 

Lorsque vous voulez que vos outfiles compressés, modifiez la commande awk: Let est print les fichiers remplis et utiliser xargs pour les gzip.

0

Si le découpage basé sur le contenu du fichier fonctionne pour vous. Essayez:

zcat originalFile.gct.gz | awk -F$',' '{print $0 | "gzip > /tmp/name_"$1".gct.gz";}'

et par exemple la ligne de mon dossier était: 2014,daniel,2,1,2,3

Je partageais les fichiers pour l'année (première colonne) en utilisant le

0

Si Spliting en fonction du contenu de le fichier fonctionne pour vous. Essayez:

zcat originalFile.gct.gz | awk -F$',' '{print $0 | "gzip > /tmp/file_"$1".gct.gz";}' 

et par exemple la ligne de mon dossier était:

2014,daniel,2,1,2,3 

Je partageais les fichiers pour l'année (première colonne) en utilisant la variable 1

$ Obtenir et ouput de:

/tmp/file_2014.gct.gz 
/tmp/file_2015.gct.gz 
/tmp/file_2016.gct.gz 
/tmp/file_2017.gct.gz 
/tmp/file_2018.gct.gz