Створіть Pandas DataFrame з рядка


276

Для того щоб перевірити деяку функціональність, я хотів би створити a DataFrameз рядка. Скажімо, мої дані тесту виглядають так:

TESTDATA="""col1;col2;col3
1;4.4;99
2;4.5;200
3;4.7;65
4;3.2;140
"""

Який найпростіший спосіб прочитати ці дані в Pandas DataFrame?

Відповіді:


497

Простий спосіб зробити це - використовувати StringIO.StringIO(python2) або io.StringIO(python3) і передати це pandas.read_csvфункції. Наприклад:

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

7
Якщо вам потрібен код, сумісний як з Python 2, так і з 3, ви необов'язково можете також використовувати from pandas.compat import StringIO, зазначивши, що це той самий клас, що і той, що поставляється з Python.
Acumenus

3
FYI - pd.read_table()це еквівалент функції, тільки трохи краще номенклатура: df = pd.read_table(TESTDATA, sep=";").
wkzhu

5
@AntonvBR Помітив, що можна користуватися pandas.compat.StringIO. Таким чином, нам не потрібно імпортувати StringIOокремо. Однак pandas.compatпакунок вважається приватним відповідно до pandas.pydata.org/pandas-docs/stable/api.html?highlight=compat, тому відповідь залишається такою, як зараз.
Еміль Н


Якщо ви створюєте TESTDATA за допомогою df.to_csv(TESTDATA), використовуйтеTESTDATA.seek(0)
user3226167

18

Метод розщеплення

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

2
Якщо ви хочете, щоб перший рядок використовувався для назв стовпців, змініть другий рядок на цей:df = pd.DataFrame([x.split(';') for x in data.split('\n')[1:]], columns=[x for x in data.split('\n')[0].split(';')])
Mabyn

1
Це неправильно, оскільки у файлах CSV символ нового рядка (\ n) може бути частиною поля.
Антоніо Ерколе де Лука

Це не дуже надійно, і більшість людей краще прийме відповідь. На сайті thomasburette.com/blog/2014/05/25/…
DanB

10

Швидке та просте рішення для інтерактивної роботи - скопіювати та вставити текст, завантаживши дані з буфера обміну.

Виберіть вміст рядка за допомогою миші:

Скопіюйте дані для вставки в рамку даних Pandas

У використанні оболонки Python 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

Скористайтеся відповідним роздільником:

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

2
Не добре для відтворюваності, але в іншому випадку досить акуратне рішення!
Мейбін

5

Традиційний CSV змінної ширини не читається для зберігання даних у вигляді рядкової змінної. Спеціально для використання всередині .pyфайлу слід розглянути дані, розділені на трубу фіксованої ширини. Різні IDE та редактори можуть мати плагін для форматування тексту, розділеного на трубу, в акуратну таблицю.

Використання read_csv

Зберігайте наступне у модулі утиліти, наприклад util/pandas.py. Приклад включений у docstring функції.

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)

Неробочі альтернативи

Код, наведений нижче, не працює належним чином, оскільки додає порожній стовпець зліва та справа.

df = pd.read_csv(io.StringIO(df_str), sep=r'\s*\|\s*', engine='python')

Що стосується read_fwf, він насправді не використовує стільки необов'язкових kwargs, які read_csvприймає та використовує. Таким чином, він взагалі не повинен використовуватися для даних, розділених на трубу.


1
Я виявив (методом проб і помилок), що read_fwfбере більше read_csvаргументів s, ніж це зафіксовано, але це правда, що деякі не мають ефекту .
Герріт

-4

Найпростіший спосіб - зберегти його в темп-файлі, а потім прочитати його:

import pandas as pd

CSV_FILE_NAME = 'temp_file.csv'  # Consider creating temp file, look URL below
with open(CSV_FILE_NAME, 'w') as outfile:
    outfile.write(TESTDATA)
df = pd.read_csv(CSV_FILE_NAME, sep=';')

Правильний спосіб створення тимчасового файлу: Як я можу створити tmp-файл у Python?


що робити, якщо немає дозволу на створення файлу?
BingLi224

На мою думку, це вже не найпростіший випадок. Зауважте, що "найпростіший" у питанні прямо вказано.
QtRoS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.