IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Trier fichier csv


Sujet :

Python

  1. #1
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut Trier fichier csv
    Bonjour,

    Bon j'espère ne pas poster pour rien mais, là, je commence à m'embourber sérieusement...
    J'ai cherché sur le forum mais je n'ai pas trouvé de sujet correspondant à mon besoin qui me parait pourtant tout bête.

    Voilà, j'aimerais trier un fichier csv se présentant de la sorte (exemple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    28.045 ;13; A ; Commentaire 1024
    28.061 ;17; A ; Commentaire 1153
    28.048 ;14; B ; Commentaire 965
    28.064 ;15; C ; Commentaire 453
    28.110 ;11; D ; Commentaire 854
    28.144 ;20; D ; Commentaire 243
    28.151 ;19; E ; Commentaire 52
    28.148 ;16; E ; Commentaire 1021
    28.172 ;18; E ; Commentaire 111
    Ici, le tri serait à faire sur le premier champs.

    Je n'ai rien trouvé dans le module csv (ou sinon j'ai loupé un truc).
    Sinon, je m'orientais vers une solution qui me semblait de plus en plus tordu, comme passer par une liste pour récupérer chaque ligne, trier cette liste, et la réinjecter dans un nouveau fichier... et là, je me suis mis à patauger..

    Merci d'avance pour votre aide.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne vois pas comment on pourrait trier sans lire le fichier et le réécrire après le tri. A part de créer un fichier index en mémoire, ce qui serait justifié si le fichier était très gros.

    Alors, si les lignes du fichier sont aussi simples que ça, partons sur la solution "tordue"

    Après lecture du fichier, on a une liste comme suit (attention à l'exemple fourni: en principe, les fichiers csv n'ont pas d'espace à côté du séparateur):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    L = [
    "28.045 ;13; A ; Commentaire 1024",
    "28.061 ;17; A ; Commentaire 1153",
    "28.048 ;14; B ; Commentaire 965",
    "28.064 ;15; C ; Commentaire 453",
    "28.110 ;11; D ; Commentaire 854",
    "28.144 ;20; D ; Commentaire 243",
    "28.151 ;19; E ; Commentaire 52",
    "28.148 ;16; E ; Commentaire 1021",
    "28.172 ;18; E ; Commentaire 111"]
    Il faut découper chaque élément de cette liste avec le ';':

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R = [e.split(';')  for e in L]
    Ce qui donne pour R:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ['28.045 ', '13', ' A ', ' Commentaire 1024']
    ['28.061 ', '17', ' A ', ' Commentaire 1153']
    ['28.048 ', '14', ' B ', ' Commentaire 965']
    ['28.064 ', '15', ' C ', ' Commentaire 453']
    ['28.110 ', '11', ' D ', ' Commentaire 854']
    ['28.144 ', '20', ' D ', ' Commentaire 243']
    ['28.151 ', '19', ' E ', ' Commentaire 52']
    ['28.148 ', '16', ' E ', ' Commentaire 1021']
    ['28.172 ', '18', ' E ', ' Commentaire 111']
    On tri selon le 1er élément, mais comme le nombre est une chaine, il faut le convertir en flottant pendant le tri:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R.sort(key=lambda v: float(v[0]))
    Ce qui donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ['28.045 ', '13', ' A ', ' Commentaire 1024']
    ['28.061 ', '17', ' A ', ' Commentaire 1153']
    ['28.048 ', '14', ' B ', ' Commentaire 965']
    ['28.064 ', '15', ' C ', ' Commentaire 453']
    ['28.110 ', '11', ' D ', ' Commentaire 854']
    ['28.144 ', '20', ' D ', ' Commentaire 243']
    ['28.151 ', '19', ' E ', ' Commentaire 52']
    ['28.148 ', '16', ' E ', ' Commentaire 1021']
    ['28.172 ', '18', ' E ', ' Commentaire 111']
    Il faut ensuite reformer la liste de chaine pour l'enregistrer sur disque:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    F = [';'.join(e) for e in R]
    Ce qui donne enfin:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    28.045 ;13; A ; Commentaire 1024
    28.048 ;14; B ; Commentaire 965
    28.061 ;17; A ; Commentaire 1153
    28.064 ;15; C ; Commentaire 453
    28.110 ;11; D ; Commentaire 854
    28.144 ;20; D ; Commentaire 243
    28.148 ;16; E ; Commentaire 1021
    28.151 ;19; E ; Commentaire 52
    28.172 ;18; E ; Commentaire 111
    Qu'il ne reste plus qu'à enregistrer sur le disque.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Merci Tyrtamos.

    Après quelques tests, il semblerait effectivement que ça marche.

    Il me reste 2 trucs importants néanmoins :
    - comprendre en détail le code que tu m'as fourni
    - reformer correctement mon fichier csv de sortie car je bute encore sur cette partie (c'est surement rien car pour l'instant je retrouve bien mes données dans mon fichier... mais ça reste sur une seule ligne)

    Par contre, par curiosité, tu parlais de "créer un fichier index en mémoire, ce qui serait justifié si le fichier était très gros".
    Qu'entends tu par là ? Car effectivement, mon fichier pourrait être gros (je n'ai fourni qu'un extrait dans mon exemple).

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par memento80 Voir le message
    Par contre, par curiosité, tu parlais de "créer un fichier index en mémoire, ce qui serait justifié si le fichier était très gros".
    Qu'entends tu par là ? Car effectivement, mon fichier pourrait être gros (je n'ai fourni qu'un extrait dans mon exemple).
    Pour les fichiers tellement gros qu'ils ne peuvent tenir en mémoire, le principe est simple (le code l'est moins...):
    - on ne charge pas le fichier en mémoire, mais on peut en lire chaque ligne séparément.
    - on crée une liste d'entier (=index), chaque entier donnant l'adresse (l'offset) de chaque ligne sur disque.
    - on peut ensuite trier la liste d'index en fonction de la ligne pointée par l'adresse.
    - après, la liste d'index permet de retrouver triées toutes les lignes du fichier sur disque.
    - on peut même retrouver l'une des lignes grâce à une recherche par dichotomie (on retrouve quasi instantanément une ligne dans un fichier d'un million de lignes: c'est impressionnant).
    - on peut enregistrer sur disque la liste des index pour la retrouver plus tard.

    Généralement, on utilise ça avec un fichier à accès direct (chaque ligne prend exactement la même longueur). Mais on peut l'appliquer avec des lignes de longueurs différentes avec l'adresse de chaque ligne en octets depuis le début du fichier.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    tyrtamos,

    j'vois pas pourquoi tu split() et tu float() ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    >>> L = [
    ... "28.045 ;13; A ; Commentaire 1024",
    ... "28.061 ;17; A ; Commentaire 1153",
    ... "28.048 ;14; B ; Commentaire 965",
    ... "28.064 ;15; C ; Commentaire 453",
    ... "28.110 ;11; D ; Commentaire 854",
    ... "28.144 ;20; D ; Commentaire 243",
    ... "28.151 ;19; E ; Commentaire 52",
    ... "28.148 ;16; E ; Commentaire 1021",
    ... "28.172 ;18; E ; Commentaire 111"]
    >>> sorted(L)
    ['28.045 ;13; A ; Commentaire 1024',
    '28.048 ;14; B ; Commentaire 965', 
    '28.061 ;17; A ; Commentaire 1153',
    '28.064 ;15; C ; Commentaire 453', 
    '28.110 ;11; D ; Commentaire 854', 
    '28.144 ;20; D ; Commentaire 243',
    '28.148 ;16; E ; Commentaire 1021',
    '28.151 ;19; E ; Commentaire 52',
    '28.172 ;18; E ; Commentaire 111']

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour josmiley,

    Citation Envoyé par josmiley Voir le message
    j'vois pas pourquoi tu split() et tu float() ...
    Simplification apparemment astucieuse, mais:

    Pour le float: dans le cas général, la comparaison entre 2 nombres ne donne pas toujours le même résultat que la comparaison entre ces mêmes nombres convertis en chaines de caractères.

    Exemple 1: 18.172 > 9.458 mais "18.172" < "9.458"

    Exemple 2: 4.079e-06 < 0.753 mais "4.079e-06" > "0.753"

    Et pour le split: si on ne fait pas, la comparaison entre 2 nombres de longueurs différentes impliquera le caractère séparateur ';' et les suivants.

    Exemple: 2.87819 > 2.8781 mais "2.87819" < "2.8781;".

    Ta solution marche ici parce que les nombres fournis ont la même structure et la même longueur xx.xxx (et qu'ils sont, en plus, dans la 1ère colonne que l'on veut trier).

    Mais ce ne serait pas raisonnable de mettre un code qui ne marche que dans ce cas particulier.

    ------------------------------------------
    PS: uniquement pour le plaisir, les 3 formules de mon 1er message peuvent être mises en un seule ligne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    F = [';'.join(e) for e in sorted([e.split(';')  for e in L], key=lambda v: float(v[0]))  ]
    Mais ça ne contribue pas à sa lisibilité...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    oui effectivement ...

  8. #8
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Merci beaucoup. Ca marche effectivement au poil.

    Vu l'explication, je ne pense pas que mes fichiers soient assez gros pour avoir à utiliser la deuxième méthode.
    Je la garde sous le coude quand même...

    A+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/04/2015, 10h07
  2. trier un fichier csv
    Par marco056 dans le forum Général Python
    Réponses: 14
    Dernier message: 10/04/2015, 01h28
  3. Trier le contenu d'un fichier .csv
    Par KiraX10A dans le forum C++
    Réponses: 9
    Dernier message: 18/09/2009, 16h37
  4. [CSV] Trier un fichier CSV
    Par arnaudperfect dans le forum Langage
    Réponses: 9
    Dernier message: 11/02/2008, 19h10
  5. Mise à jour d'une table avec un fichier csv
    Par blackangel dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 26/05/2005, 14h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo