Tạo Pandas DataFrame từ một chuỗi


275

Để kiểm tra một số chức năng, tôi muốn tạo DataFramemột chuỗi. Giả sử dữ liệu thử nghiệm của tôi trông như sau:

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

Cách đơn giản nhất để đọc dữ liệu đó vào Pandas là DataFramegì?

Câu trả lời:


493

Một cách đơn giản để làm điều này là sử dụng StringIO.StringIO(python2) hoặc io.StringIO(python3) và truyền nó cho pandas.read_csvhàm. Ví dụ:

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
Nếu bạn cần mã tương thích với cả Python 2 và 3, bạn cũng có thể tùy ý sử dụng from pandas.compat import StringIO, lưu ý rằng đó là cùng một lớp với mã đi kèm với Python.
Acumenus

3
FYI - pd.read_table()là một chức năng tương đương, chỉ là danh pháp tốt hơn một chút : df = pd.read_table(TESTDATA, sep=";").
wkzhu

5
@AntonvBR Lưu ý rằng người ta có thể sử dụng pandas.compat.StringIO. Bằng cách đó, chúng tôi không phải nhập StringIOriêng. Tuy nhiên, pandas.compatgói được coi là riêng tư theo pandas.pydata.org/pandas-docs/urdy/api.html?highlight=compat vì vậy hãy để lại câu trả lời như hiện tại.
Emil H


Nếu bạn tạo TESTDATA với df.to_csv(TESTDATA), hãy sử dụngTESTDATA.seek(0)
user3226167

18

Phương pháp phân chia

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

2
Nếu bạn muốn dòng đầu tiên được sử dụng cho tên cột, hãy thay đổi dòng thứ 2 thành dòng này:df = pd.DataFrame([x.split(';') for x in data.split('\n')[1:]], columns=[x for x in data.split('\n')[0].split(';')])
Mabyn

1
Điều này là sai, vì trên các tệp CSV, ký tự dòng mới (\ n) có thể là một phần của một trường.
Antonio Ercole De Luca

Điều này không phải là rất mạnh mẽ, và hầu hết mọi người sẽ tốt hơn với câu trả lời được chấp nhận. Có một danh sách rất cục bộ những thứ có thể đi sai với điều này tại thomasburette.com/blog/2014/05/25/...
DanB

10

Một giải pháp nhanh chóng và dễ dàng cho công việc tương tác là sao chép và dán văn bản bằng cách tải dữ liệu từ bảng ghi tạm.

Chọn nội dung của chuỗi bằng chuột của bạn:

Sao chép dữ liệu để dán vào khung dữ liệu Pandas

Trong trình bao Python, sử dụng 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

Sử dụng dấu phân cách thích hợp:

>>> 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
Không tốt cho khả năng tái tạo, nhưng nếu không thì một giải pháp khá gọn gàng!
Mabyn

5

Không thể đọc được CSV có chiều rộng biến truyền thống để lưu trữ dữ liệu dưới dạng biến chuỗi. Đặc biệt là để sử dụng bên trong một .pytệp, thay vào đó hãy xem xét dữ liệu được phân tách bằng ống có chiều rộng cố định. Nhiều IDE và trình soạn thảo khác nhau có thể có một plugin để định dạng văn bản được phân tách bằng ống thành một bảng gọn gàng.

Sử dụng read_csv

Lưu trữ sau đây trong một mô-đun tiện ích, ví dụ util/pandas.py. Một ví dụ được bao gồm trong chuỗi của hàm.

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)

Giải pháp thay thế không làm việc

Mã dưới đây không hoạt động đúng bởi vì nó thêm một cột trống ở cả bên trái và bên phải.

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

Về phần read_fwf, nó không thực sự sử dụng rất nhiều kwarg tùy chọn read_csvchấp nhận và sử dụng. Vì vậy, nó hoàn toàn không nên được sử dụng cho dữ liệu được phân tách bằng đường ống.


1
Tôi đã tìm thấy (bằng cách dùng thử & lỗi) read_fwfcó nhiều read_csvđối số hơn so với tài liệu, nhưng đúng là một số không có hiệu lực .
gerrit

-4

Cách đơn giản nhất là lưu nó vào tệp tạm thời và sau đó đọc nó:

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

Cách đúng để tạo tệp tạm thời: Làm cách nào tôi có thể tạo tệp tmp trong Python?


Nếu không có quyền tạo tập tin thì sao?
BingLi224

Theo tôi đó không phải là trường hợp đơn giản nhất nữa. Lưu ý rằng "đơn giản nhất" được nêu rõ ràng trong câu hỏi.
QtRoS ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.