web-dev-qa-db-fra.com

Comment convertir des feuilles de calcul OpenDocument en un DataFrame?

La bibliothèque Python pandas peut lire les feuilles de calcul Excel et les convertir en commande pandas.DataFrame avec pandas.read_Excel(file). Sous le capot, il utilise xlrd bibliothèque qui ne supporte pas les fichiers ods.

Existe-t-il un équivalent de pandas.read_Excel pour les fichiers ods? Si non, comment puis-je faire de même pour une feuille de calcul Open Document Formatatted (fichier ods)? ODF est utilisé par LibreOffice et OpenOffice.

30
Lamps1829

Vous pouvez lire des documents ODF (Open Document Format .ods) en Python en utilisant les modules suivants:

En utilisant ezodf, un convertisseur simple de ODS à DataFrame pourrait ressembler à ceci:

import pandas as pd
import ezodf

doc = ezodf.opendoc('some_odf_spreadsheet.ods')

print("Spreadsheet contains %d sheet(s)." % len(doc.sheets))
for sheet in doc.sheets:
    print("-"*40)
    print("   Sheet name : '%s'" % sheet.name)
    print("Size of Sheet : (rows=%d, cols=%d)" % (sheet.nrows(), sheet.ncols()) )

# convert the first sheet to a pandas.DataFrame
sheet = doc.sheets[0]
df_dict = {}
for i, row in enumerate(sheet.rows()):
    # row is a list of cells
    # assume the header is on the first row
    if i == 0:
        # columns as lists in a dictionary
        df_dict = {cell.value:[] for cell in row}
        # create index for the column headers
        col_index = {j:cell.value for j, cell in enumerate(row)}
        continue
    for j, cell in enumerate(row):
        # use header instead of column index
        df_dict[col_index[j]].append(cell.value)
# and convert to a DataFrame
df = pd.DataFrame(df_dict)

P.S.

  • La prise en charge des feuilles de calcul ODF (fichiers * .ods) a été demandée sur l'outil de suivi des problèmes pandas: https://github.com/pydata/pandas/issues/2311 , mais n'est toujours pas implémenté.

  • ezodf a été utilisé dans l'inachevé PR9070 pour mettre en œuvre le soutien ODF dans les pandas. Ce PR est maintenant fermé (lisez le PR pour une discussion technique), mais il est toujours disponible à titre expérimental dans thispandas fork.

  • il existe aussi des méthodes de force brute pour lire directement à partir du code XML ( ici )
12
davidovitch

Voici un hack rapide et sale qui utilise ezodf module:

import pandas as pd
import ezodf

def read_ods(filename, sheet_no=0, header=0):
    tab = ezodf.opendoc(filename=filename).sheets[sheet_no]
    return pd.DataFrame({col[header].value:[x.value for x in col[header+1:]]
                         for col in tab.columns()})

Tester:

In [92]: df = read_ods(filename='fn.ods')

In [93]: df
Out[93]:
     a    b    c
0  1.0  2.0  3.0
1  4.0  5.0  6.0
2  7.0  8.0  9.0

REMARQUES: 

  • tous les autres paramètres utiles comme header, skiprows, index_col, parse_cols NE sont PAS implémentés dans cette fonction - n'hésitez pas à mettre à jour cette question si vous souhaitez les implémenter
  • ezodf dépend de lxml assurez-vous de l'avoir installé
8
MaxU

Une autre option: read-ods-with-odfpy . Ce module prend en entrée une feuille de calcul OpenDocument et renvoie une liste à partir de laquelle un DataFrame peut être créé.

3
Lamps1829

Il semblerait que la réponse soit non! Et je décrirais les outils pour lire dans ODS encore en lambeaux . Si vous êtes sur POSIX, peut-être que la stratégie d'exportation au format xlsx à la volée avant d'utiliser le très bel import de Pandas outils pour xlsx est une option:

unoconv -f xlsx -o tmp.xlsx myODSfile.ods 

Au total, mon code ressemble à:

import pandas as pd
import os
if fileOlderThan('tmp.xlsx','myODSfile.ods'):
    os.system('unoconv -f xlsx -o tmp.xlsx myODSfile.ods ')
xl_file = pd.ExcelFile('tmp.xlsx')
dfs = {sheet_name: xl_file.parse(sheet_name) 
          for sheet_name in xl_file.sheet_names}
df=dfs['Sheet1']

FileOlderThan () est ici une fonction (voir http://github.com/cpbl/cpblUtilities ) qui renvoie true si le fichier tmp.xlsx n'existe pas ou est plus ancien que le fichier .ods. 

2
CPBL

J'ai eu de la chance avec les pandas read_clipboard . Sélection de cellules puis copie depuis Excel ou opendocument . En python, exécutez ce qui suit.

import pandas as pd
data = pd.read_clipboard()

Les pandas feront un bon travail en se basant sur les cellules copiées.

1
Mike Adrion

Si vous n'avez que quelques fichiers .ods à lire, je voudrais simplement l'ouvrir dans openoffice et l'enregistrer en tant que fichier Excel. Si vous avez beaucoup de fichiers, vous pouvez utiliser la commande unoconv sous Linux pour convertir les fichiers .ods en .xls par programme ( avec bash )

Alors c'est vraiment facile de le lire avec pd.read_Excel('filename.xls')

1
wordsforthewise

La prise en charge de la lecture de fichiers Excel dans les pandas (xls et xlsx) est décrite dans la commande read_Excel . Vous pouvez utiliser OpenOffice pour enregistrer la feuille de calcul au format xlsx. La conversion peut également être effectuée automatiquement sur la ligne de commande, apparemment, en utilisant le paramètre de ligne de commande -convert-to .

La lecture des données à partir de xlsx évite certains problèmes (formats de date, formats de nombre, unicode) que vous pouvez rencontrer lors de la première conversion au format CSV.

0
Matthias Berth

Si possible, enregistrez au format CSV à partir de l'application de feuille de calcul, puis utilisez pandas.read_csv(). IIRC, un fichier tableur "ods" est en fait un fichier XML qui contient également pas mal d'informations de formatage. Donc, s’il s’agit de données tabulaires, extrayez d’abord ces données brutes dans un fichier intermédiaire (CSV, dans ce cas), que vous pourrez ensuite analyser avec d’autres programmes, tels que Python/pandas.

0
Jan-Philip Gehrcke

Sur la base de la réponse de davidovitch (merci), j’ai rassemblé un package qui lit un fichier .ods et renvoie un DataFrame. Ce n'est pas une implémentation complète dans pandas lui-même, comme son PR, mais elle fournit une simple fonction read_ods qui fait le travail.

Vous pouvez l'installer avec pip install pandas_ods_reader. Il est également possible de spécifier si le fichier contient ou non une ligne d'en-tête et de spécifier des noms de colonne personnalisés.

0
iuvbio