Afin de tester certaines fonctionnalités, j'aimerais créer une DataFrame
à partir d'une chaîne. Disons que mes données de test ressemblent à:
TESTDATA="""col1;col2;col3
1;4.4;99
2;4.5;200
3;4.7;65
4;3.2;140
"""
Quel est le moyen le plus simple de lire ces données dans un Pandas DataFrame
?
Une méthode simple consiste à utiliser StringIO
et à le transmettre à la fonction pandas.read_csv
. Par exemple:
import sys
if sys.version_info[0] < 3:
from StringIO import StringIO
else:
from io import StringIO
import pandas as pd
TESTDATA = StringIO("""col1;col2;col3
1;4.4;99
2;4.5;200
3;4.7;65
4;3.2;140
""")
df = pd.read_csv(TESTDATA, sep=";")
Un fichier CSV à largeur variable traditionnel est illisible pour stocker des données sous forme de variable chaîne. Particulièrement pour une utilisation dans un fichier .py
, tenez plutôt compte des données séparées par des tubes de largeur fixe. Différents IDE et éditeurs peuvent avoir un plugin pour formater du texte séparé par des tubes en un tableau soigné.
Ce qui suit fonctionne pour moi. Pour l'utiliser, stockez-le dans un fichier, par exemple. pandas_util.py
. Un exemple est inclus dans la docstring de la fonction. Si vous utilisez une version de Python antérieure à 3.6, supprimez les annotations de type de la ligne de définition de fonction.
import re
import pandas as pd
def read_pipe_separated_str(str_input: str, **kwargs) -> pd.DataFrame:
"""Read a Pandas object from a pipe-separated table contained within a string.
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(pd.compat.StringIO(str_input), sep='|', **kwargs)
Le code ci-dessous ne fonctionne pas correctement car il ajoute une colonne vide à gauche et à droite.
df = pd.read_csv(pd.compat.StringIO(df_str), sep=r'\s*\|\s*', engine='python')
Une solution simple et rapide pour le travail interactif consiste à copier-coller le texte en chargeant les données à partir du presse-papiers.
Sélectionnez le contenu de la chaîne avec votre souris:
Dans le shell Python, utilisez read_clipboard()
>>> pd.read_clipboard()
col1;col2;col3
0 1;4.4;99
1 2;4.5;200
2 3;4.7;65
3 4;3.2;140
Utilisez le séparateur approprié:
>>> pd.read_clipboard(sep=';')
col1 col2 col3
0 1 4.4 99
1 2 4.5 200
2 3 4.7 65
3 4 3.2 140
>>> df = pd.read_clipboard(sep=';') # save to dataframe
Méthode Split
x = input_string
df = pd.DataFrame([x.split(';') for x in data.split('\n')])
print(df)