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

Calcul scientifique Python Discussion :

Pandas Dataframe append


Sujet :

Calcul scientifique Python

  1. #1
    Membre régulier
    Profil pro
    Pôle Etude et Automatisation
    Inscrit en
    Avril 2007
    Messages
    166
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Pôle Etude et Automatisation
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2007
    Messages : 166
    Points : 100
    Points
    100
    Par défaut Pandas Dataframe append
    Bonsoir,

    J'essaie de concaténer des dataframes à partir du code suivant:

    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
     
    import tarfile
     
    df2 = pd.DataFrame(columns=our_list)
     
    with tarfile.open('V2_GLFI.tar.gz', 'r:*') as tar:
     
        for n in tar.getnames():
     
            if n.endswith('.TXT'):
     
                try:
     
                    df = pd.read_fwf(tar.extractfile(n),colspecs=resultNumCar, header=None, names=our_list,encoding="utf_8_sig")
     
                    df2.append(df, ignore_index=True)
     
                except pd.errors.EmptyDataError:
     
                    continue
    le dataframe df2 reste vide bien qu'un print(df) me montre à chaque tour un nouveau dataframe df?

    Merci
    Eric

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Ouvrez la documentation, çà dit que .append retourne un nouveau dataframe (pas que çà modifie le courant) et qu'il y a des méthodes peut être plus efficaces.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre régulier
    Profil pro
    Pôle Etude et Automatisation
    Inscrit en
    Avril 2007
    Messages
    166
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Pôle Etude et Automatisation
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2007
    Messages : 166
    Points : 100
    Points
    100
    Par défaut
    Bonjour,

    je l'avais lu

    Nom : Capture d’écran 2021-04-08 100824.png
Affichages : 86
Taille : 18,5 Ko

    mais ne l'avez pas compris ainsi

    Je voulais seulement appliquer l'exemple ci-dessous dans une boucle

    Nom : Capture d’écran 2021-04-08 100930.png
Affichages : 84
Taille : 11,9 Ko

    Merci
    Eric

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Pourtant çà dit bien "returning a new object"... et les exemples données à la suite sont assez éclairants.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    D'abord, je ne pense pas que l'extension .TXT soit une norme, elle s'écrit souvent même comme .txt ... Il faut mieux faire un texte plus souple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            #if n.endswith('.TXT'):
            if n.upper().endswith('.TXT'):
    Et puis, comme souligné déjà, append() retourne un DataFrame qui est le résultat d'append() qu'il faut le capturer pour qu'on puisse travailler dessus. L'exemple en IPython démontre sous-entendu un display() sur le DataFrame résulté et retourné. En pratique dans un script python, çelà se fait comme ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                    #df2.append(df, ignore_index=True)
                    df2=df2.append(df, ignore_index=True)
    Voilà !

  6. #6
    Membre régulier
    Profil pro
    Pôle Etude et Automatisation
    Inscrit en
    Avril 2007
    Messages
    166
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Pôle Etude et Automatisation
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2007
    Messages : 166
    Points : 100
    Points
    100
    Par défaut
    Merci tsuji,

    j'ai réussi avec

    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
    21
    22
    23
     
     
    import tarfile
     
    df = pd.DataFrame(columns=our_list)
     
    with tarfile.open('EE.tar.gz', 'r:*') as tar:
     
        for n in tar.getnames():
     
            if n.endswith('.TXT'):
     
                try:
     
                    df_new_line = pd.read_fwf(tar.extractfile(n),colspecs=resultNumCar, header=None, names=our_list,encoding="utf_8_sig")
     
                    df = pd.concat([df,df_new_line], ignore_index=True)
     
                except pd.errors.EmptyDataError:
     
                    continue
     
    df
    Il faut encore que je vide le dataframe si je relance le script sinon celui-ci s'enrichit à chaque exécution.

    Je vais tester tes suggestions et de tiens au courant.

    Eric

  7. #7
    Membre régulier
    Profil pro
    Pôle Etude et Automatisation
    Inscrit en
    Avril 2007
    Messages
    166
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Pôle Etude et Automatisation
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2007
    Messages : 166
    Points : 100
    Points
    100
    Par défaut
    Bonjour,

    J'ai testé ta suggestion et cela fonctionne correctement merci.

    Actuellement j'essaie d’optimiser le code ci-dessous. Je travaille avec des fichiers archives compressés de 5 à 15 Go. Décompressés ces fichiers ont une taille entre 150 à 300 Go. Le nombre de fichiers traités entre 100 et 200 qui vont de quelques Mo à quelques Go pour certains. Le nombre d'enregistrements plus de 150 millions de lignes avec plus de 110 champs. Les temps de traitement sont très importants 48H pour certaines jointures. Le code ci-dessous me permet d'extraire les données au format csv pour les transformer en fichiers .parquet. Je ne sais pas si je m'y prends bien. Tous ces traitements se font sur un i core 5 avec 16G0 de mémoires et 1 dd d'un To.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    import pandas as pd
     
    from dask.distributed import Client
    client = Client(n_workers=3, threads_per_worker=3, processes=True, memory_limit='40GB')
    client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    def createList(name, n):
        result = {}
        for i in range(n):
            nameList = name + str(i)
            result[nameList] = []
        return result
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #Lecture du fichier xml (GL FI)
     
    f = open("GL.XML", "r")
     
    # Détermine le nombre de lignes dans le fichier
     
    NombredeLigne = 0
     
    for line in f:
     
        NombredeLigne += 1
     
    # Revient au début du fichier après avoir déterminer le nombre de lignes
     
    f.seek(0)
     
    # Détermine le nombre de champs par ligne
     
    data = f.read()
     
    lines = data.splitlines()
     
    i = 0
     
    NombreChampsParLigne = 0
     
    for line in enumerate(lines) :
     
        s = lines[i]
     
        if s.startswith("<FixedColumn>") :
     
            NombreChampsParLigne += 1
     
            i += 1
     
        i += 1
     
        if i >= NombredeLigne :
     
            break
     
    res = createList("list", NombreChampsParLigne) # création de listes dont le nom commence par list
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    # Récupération des valeurs du fichier xml (GL FI)
     
    t = []
     
    i = 0
    j = -1
     
    debut = ""
     
    for line in enumerate(lines):
     
        s = lines[i]
     
        if s.startswith("<FixedColumn>") :
            debut = "OK"
            j += 1
     
        if debut == "OK":  
     
            if s.startswith("<Name>") :
                s = s.replace("<Name>", "")
                s = s.replace("</Name>","")
                t.append(s)
     
            if s.startswith("<Description>") :
                s = s.replace("<Description>", "")
                s = s.replace("</Description>","")
                t.append(s)
     
            if s.startswith("<AlphaNumeric/>") :
                s = s.replace("<AlphaNumeric/>", "AlphaNumeric")
                verifFormat = "no"
                t.append(s)
                w = "NaN"
                t.append(w)
     
            if s.startswith("<Numeric>") :
                s = s.replace("<Numeric>", "Numeric")
                verifFormat = "no"
                t.append(s)
                w = "NaN"
                t.append(w)
     
            if s.startswith("<Date>") :
                s = s.replace("<Date>", "Date")
                t.append(s)
                verifFormat = "yes"
     
            if s.startswith("<Format>") and verifFormat == "yes":
                s = s.replace("<Format>", "")
                s = s.replace("</Format>","")
                verifFormat = "no"
                t.append(s)
     
            if s.startswith("<From>") :
                s = s.replace("<From>", "")
                s = s.replace("</From>","")
                t.append(s)
     
            if s.startswith("<To>") :
                s = s.replace("<To>", "")
                s = s.replace("</To>","")
                t.append(s)      
     
                valList = "list" + str(j)       
     
                res[valList].extend(t) # on ajoute les valeurs à list i
     
                del t[:]
     
        i += 1
     
    my_dataframe = pd.DataFrame.from_dict(res, orient='index')
    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
     
    # Convertie la colonne 4 et 5 du dataframe (xml) en entier
    my_dataframe[4] = my_dataframe[4].astype(int)
    my_dataframe[5] = my_dataframe[5].astype(int)
     
    # Soustrait 1 aux valeurs de la colonne 4 pour être utilisées dans le fractionnement du fichier GL FI
    my_dataframe[4] = my_dataframe[4].apply(lambda x: x - 1)
     
    mycolumnsNumCar = [4, 5]
    oooNumCar = my_dataframe[mycolumnsNumCar]
     
    oooName = my_dataframe[0].to_list()
     
    our_list =[]
    for signe in oooName:
        our_list.append(signe.replace("-","_"))
     
    resultNumCar = oooNumCar.values.tolist()
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    import tarfile
     
    chunksize = 10 ** 6
    data_chunks = list()
     
    with tarfile.open('V2_GLFI.tar.gz', 'r:*') as tar:
     
        for n in tar.getnames():
     
            if n.upper().endswith('.TXT'):
     
                try: 
     
                    df = pd.read_fwf(tar.extractfile(n),colspecs=resultNumCar, header=None, names=our_list,encoding="utf_8_sig", chunksize=chunksize)
     
                    for chunk in df:
                        data_chunks.append(chunk)
     
                    dfcsv = pd.concat(data_chunks)
     
                    #dfcsv = dfcsv.assign(Somme = lambda x: x.BSEG_DMBTR * x.BSEG_SHKZG.replace({'H' : 1, 'S' : -1}))
     
                    sansStatut = pd.isnull(dfcsv["BKPF_BSTAT"])
     
                    nom = n.replace(".TXT",".csv")
     
                    filename = 'CSV/' + nom
     
                    #dfcsv[sansStatut].loc[:,['BKPF_BUKRS','BSEG_HKONT','Somme']].to_csv(filename,index=False)
                    dfcsv[sansStatut].to_csv(filename,index=False)
     
                except pd.errors.EmptyDataError:
     
                    continue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    import dask.dataframe as dd
     
    ddf = dd.read_csv('CSV/*.csv', dtype={'BKPF_BSTAT': 'object', 'BKPF_BVORG': 'object', 'BKPF_XREF2_HD': 'object', 'BKPF_XRUEB': 'object','BKPF_ZZ_AMG':'object','BKPF_ZZ_MARQUEUR':'object','BKPF_ZZ_NUMTITRE':'object','BKPF_ZZ_TXTLIB':'object','BSEG_EBELN':'object','BSEG_PPRCT':'object', 'BSEG_UMSKZ':'object','BSEG_WERKS':'object','BSEG_XREF1':'object', 'BSEG_XREF3': 'object','BSEG_ZZNATBUD':'object','BSEG_ZZ_ACTIVIT':'object','BSEG_ZZ_ANA_MIN':'object','BSEG_ZZ_AXMIN2':'object','BSEG_ZZ_NAT_MIN': 'object','BSEG_ZZ_CPER':'object','BSEG_ZZ_LOC_MIN':'object','BSEG_ZZCDEFLUX':'object','BSEG_FIPOS':'str','BSEG_GSBER':'object','BSEG_XREF2':'str','BSEG_ZZ_PRESAGE':'object','BSEG_FKBER':'object','BSEG_SEGMENT':'object','BKPF_XBLNR':'object','BSEG_ZZSEG':'object','BSEG_FISTL':'object','BSEG_ZLSCH':'object','BSEG_FKBER_LONG':'object','BKPF_AWKEY':'object','BSEG_ZUONR':'str','BSEG_SGTXT':'str','BSEG_PARGB':'object','BSEG_BEWAR':'object','BSEG_LIFNR':'object','BSEG_VBEWA':'object','BSEG_BUZID':'object','BSEG_ZZ_AXMIN1':'object','BSEG_ZZ_TF':'object','BSEG_XNEGP':'object'})
     
    #ddf = dd.read_csv('CSV/*.csv')
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ddf.to_parquet('PAR/2021-01.parquet', engine='pyarrow')
    Merci pour vos observations

    Eric

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Pour vous aider il faudrait pouvoir "tester" pour faire du profiling de votre code (voir ou çà passe le plus de temps) et/ou le remettre à plat.

    Citation Envoyé par Eric_03 Voir le message
    Tous ces traitements se font sur un i core 5 avec 16G0 de mémoires et 1 dd d'un To.
    Vous devez déjà calculer la bande passante de votre système pour avoir une estimation du temps que çà devrait prendre dans ce dimensionnement "physique".
    Vous pouvez aussi regarder quelles sont les ressources consommées pour voir ou çà peut coincer.

    note: plein de données => beaucoup d'entrées/sortie => parallélisation entre contrôleurs/disques. Une bécane pour stocker des vidéos (un seul disque de 1 To) n'a rien à voir avec une machine pour faire des IO (plein de petits disques en stripe).

    Je ne dis pas qu'il n'y a rien à gratter en lisant votre code, juste que il y a des préalables à vérifier avant de s'y plonger... et beaucoup de boulot qu'on ne peut pas faire sur un coin de table (un forum de discussion).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 0
    Dernier message: 28/11/2019, 19h06
  2. Pandas - DataFrame - Problème de resampling
    Par Gabriel_1234 dans le forum Général Python
    Réponses: 2
    Dernier message: 22/08/2019, 14h57
  3. [pandas] pandas.DataFrame : Comment ajouter une ligne ?
    Par Oblinky dans le forum Bibliothèques tierces
    Réponses: 2
    Dernier message: 23/07/2018, 09h52
  4. [Python 3.x] Pandas Dataframe selection
    Par thais781 dans le forum Général Python
    Réponses: 3
    Dernier message: 12/03/2018, 18h04
  5. Import .txt vers Panda Dataframe, problème header
    Par pwetzou dans le forum Général Python
    Réponses: 12
    Dernier message: 03/02/2017, 09h37

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