Xử lý số cột biến với gấu trúc - Python


76

Tôi có một tập dữ liệu trông như thế này (nhiều nhất là 5 cột - nhưng có thể ít hơn)

1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
....

Tôi đang cố gắng sử dụng pandas read_table để đọc nó thành một khung dữ liệu 5 cột. Tôi muốn đọc cái này mà không cần xoa bóp thêm.

Nếu tôi cố gắng

import pandas as pd
my_cols=['A','B','C','D','E']
my_df=pd.read_table(path,sep=',',header=None,names=my_cols)

Tôi gặp lỗi - "tên cột có 5 trường, dữ liệu có 3 trường".

Có cách nào khiến gấu trúc điền NaN vào các cột còn thiếu trong khi đọc dữ liệu không?

Câu trả lời:


80

Một cách có vẻ hoạt động (ít nhất là trong 0.10.1 và 0.11.0.dev-fc8de6d):

>>> !cat ragged.csv
1,2,3
1,2,3,4
1,2,3,4,5
1,2
1,2,3,4
>>> my_cols = ["A", "B", "C", "D", "E"]
>>> pd.read_csv("ragged.csv", names=my_cols, engine='python')
   A  B   C   D   E
0  1  2   3 NaN NaN
1  1  2   3   4 NaN
2  1  2   3   4   5
3  1  2 NaN NaN NaN
4  1  2   3   4 NaN

Tuy nhiên, lưu ý rằng cách tiếp cận này yêu cầu bạn đặt tên cho các cột bạn muốn. Không chung chung như một số cách khác, nhưng đủ hiệu quả khi áp dụng.


2
Cảm ơn bạn! Điều này đã hiệu quả - engine = 'python' dường như là chìa khóa. Thêm thuộc tính này làm cho cả read_table và read_csv đều hoạt động.
Jackie Shephard

2
Điều này có vẻ khá buồn đối với tôi. Thêm một vấn đề github: github.com/pydata/pandas/issues/2981
Wes McKinney

1
Điều đã sửa nó cho tôi là names=my_colsnơi my_colsít nhất là dài nhất là dòng có nhiều trường nhất. Nếu số lượng trường tối đa không được biết trước, bạn có thể giải nén động bằng cách đọc trước tệp qua with open('my.csv') as f: num_cols = max(len(line.split(',')) for line in f); f.seek(0); df = pd.read_csv(f, names=range(num_cols)) nhưng mặt trái là tệp được đọc hai lần.
EliadL

với phiên bản Pandas 0.23.4 pd.read_csv(file, names=my_cols)hoạt động ngay cả khi len(my_cols)ít hơn số trường trên một hoặc nhiều dòng. Các trường bổ sung sẽ bị loại bỏ.
Luca Amerio

với gấu trúc 0,25.3 nó không thành công nếu một số cột dài hơn my_cols
Gena Kukartsev

16

Tôi cũng muốn biết liệu điều này có khả thi hay không, từ tài liệu có vẻ như không phải vậy. Những gì bạn có thể làm là đọc từng dòng của tệp và nối mỗi lần đọc với DataFrame:

import pandas as pd

df = pd.DataFrame()

with open(filepath, 'r') as f:
    for line in f:
        df = pd.concat( [df, pd.DataFrame([tuple(line.strip().split(','))])], ignore_index=True )

Nó hoạt động nhưng không phải theo cách thanh lịch nhất, tôi đoán ...


1

Đồng ý. Không chắc điều này hiệu quả đến mức nào - nhưng đây là những gì tôi đã làm. Rất muốn nghe nếu có cách tốt hơn để làm điều này. Cảm ơn !

from pandas import DataFrame

list_of_dicts=[]
labels=['A','B','C','D','E']
for line in file:
    line=line.rstrip('\n')
    list_of_dicts.append(dict(zip(labels,line.split(','))))
frame=DataFrame(list_of_dicts)
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.