Cette réponse s'applique lorsqu'une chaîne est entrée manuellement, pas lorsqu'elle est lue quelque part.
Un CSV traditionnel à largeur variable est illisible pour stocker des données sous forme de variable de chaîne. Surtout pour une utilisation à l'intérieur d'un .py
fichier, pensez plutôt aux données séparées par des tuyaux de largeur fixe. Divers IDE et éditeurs peuvent avoir un plugin pour formater le texte séparé par des tuyaux dans une table soignée.
Stockez les éléments suivants dans un module utilitaire, par exemple util/pandas.py
. Un exemple est inclus dans la docstring de la fonction.
import io
import re
import pandas as pd
def read_psv(str_input: str, **kwargs) -> pd.DataFrame:
"""Read a Pandas object from a pipe-separated table contained within a string.
Input example:
| int_score | ext_score | eligible |
| | 701 | True |
| 221.3 | 0 | False |
| | 576 | True |
| 300 | 600 | True |
The leading and trailing pipes are optional, but if one is present,
so must be the other.
`kwargs` are passed to `read_csv`. They must not include `sep`.
In PyCharm, the "Pipe Table Formatter" plugin has a "Format" feature that can
be used to neatly format a table.
Ref: https://stackoverflow.com/a/46471952/
"""
substitutions = [
('^ *', ''), # Remove leading spaces
(' *$', ''), # Remove trailing spaces
(r' *\| *', '|'), # Remove spaces between columns
]
if all(line.lstrip().startswith('|') and line.rstrip().endswith('|') for line in str_input.strip().split('\n')):
substitutions.extend([
(r'^\|', ''), # Remove redundant leading delimiter
(r'\|$', ''), # Remove redundant trailing delimiter
])
for pattern, replacement in substitutions:
str_input = re.sub(pattern, replacement, str_input, flags=re.MULTILINE)
return pd.read_csv(io.StringIO(str_input), sep='|', **kwargs)
Alternatives non fonctionnelles
Le code ci-dessous ne fonctionne pas correctement car il ajoute une colonne vide à gauche et à droite.
df = pd.read_csv(io.StringIO(df_str), sep=r'\s*\|\s*', engine='python')
Quant à read_fwf
, il n'utilise pas vraiment autant de kwargs optionnels qui read_csv
acceptent et utilisent. En tant que tel, il ne devrait pas être utilisé du tout pour les données séparées par des tuyaux.
from pandas.compat import StringIO
, notant qu'il s'agit de la même classe que celle fournie avec Python.