web-dev-qa-db-fra.com

Créer Pandas DataFrame à partir d'une chaîne

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?

167
Emil H

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=";")
317
Emil H

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)

Alternative non-travaillante:

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')
4
A-B-B

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:

 Copy data for pasting into a Pandas dataframe

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
1
user2314737

Méthode Split

x = input_string
df = pd.DataFrame([x.split(';') for x in data.split('\n')])
print(df)
0
shaurya uppal