Các tùy chọn read_csv low_memory và dtype


320

Khi gọi

df = pd.read_csv('somefile.csv')

Tôi có:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: Cột (4,5,7,16) có các loại hỗn hợp. Chỉ định tùy chọn dtype khi nhập hoặc đặt low_memory = false.

Tại sao dtypetùy chọn liên quan đến low_memoryvà tại sao nó lại Falsegiúp giải quyết vấn đề này?


2
Tôi có một câu hỏi về cảnh báo này. Là chỉ số của các cột được đề cập dựa trên 0? Ví dụ: cột 4 có loại hỗn hợp, đó là df [:, 4] hoặc df [:, 3]
maziar

@maziar khi đọc csv, theo mặc định, một chỉ mục dựa trên 0 mới được tạo và sử dụng.
Firelynx

Câu trả lời:


432

Tùy chọn low_memory không dùng nữa

Các low_memorytùy chọn không phản đối đúng, nhưng nó phải được, vì nó không thực sự làm bất cứ điều gì khác nhau [ nguồn ]

Lý do bạn nhận được low_memorycảnh báo này là bởi vì việc đoán các loại dtypes cho mỗi cột rất đòi hỏi bộ nhớ. Gấu trúc cố gắng xác định loại nào sẽ được đặt bằng cách phân tích dữ liệu trong mỗi cột.

Dtype Guessing (rất tệ)

Gấu trúc chỉ có thể xác định loại cột nào nên có khi toàn bộ tệp được đọc. Điều này có nghĩa là không có gì thực sự có thể được phân tích cú pháp trước khi toàn bộ tệp được đọc trừ khi bạn có nguy cơ phải thay đổi kiểu chữ của cột đó khi bạn đọc giá trị cuối cùng.

Hãy xem xét ví dụ về một tệp có một cột được gọi là user_id. Nó chứa 10 triệu hàng trong đó user_id luôn là số. Vì gấu trúc không thể biết nó chỉ là số, nên có thể nó sẽ giữ nó làm chuỗi gốc cho đến khi nó đọc được toàn bộ tệp.

Chỉ định dtypes (nên luôn luôn được thực hiện)

thêm

dtype={'user_id': int}

đến pd.read_csv()cuộc gọi sẽ làm cho gấu trúc biết khi nào nó bắt đầu đọc các tập tin, rằng đây chỉ là số nguyên.

Cũng đáng chú ý là nếu dòng cuối cùng trong tệp sẽ "foobar"được ghi trong user_idcột, quá trình tải sẽ bị sập nếu dtype ở trên được chỉ định.

Ví dụ về dữ liệu bị hỏng khi vỡ được xác định

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})

ValueError: invalid literal for long() with base 10: 'foobar'

dtypes thường là một thứ numpy, đọc thêm về chúng ở đây: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Những gì dtypes tồn tại?

Chúng tôi có quyền truy cập vào các dtypes numpy: float, int, bool, timedelta64 [ns] và datetime64 [ns]. Lưu ý rằng các loại ngày / thời gian numpy không nhận biết múi giờ.

Gấu trúc mở rộng bộ dtypes này bằng chính nó:

'datetime64 [ns,]' Đó là dấu thời gian nhận biết múi giờ.

'category' về cơ bản là một enum (chuỗi được biểu thị bằng các phím số nguyên để lưu

'period []' Không bị nhầm lẫn với timedelta, các đối tượng này thực sự được neo vào các khoảng thời gian cụ thể

'Thưa thớt', 'thưa thớt [int]', 'thưa thớt [nổi]' dành cho dữ liệu thưa thớt hoặc 'Dữ liệu có nhiều lỗ hổng trong đó' Thay vì lưu NaN hoặc Không có trong khung dữ liệu, nó bỏ qua các đối tượng, tiết kiệm không gian .

'Interval' là một chủ đề của riêng nó nhưng công dụng chính của nó là để lập chỉ mục. Xem thêm tại đây

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' đều là các số nguyên cụ thể của gấu trúc không thể tách rời, không giống như biến thể numpy.

'chuỗi' là một loại dtype cụ thể để làm việc với dữ liệu chuỗi và cấp quyền truy cập vào .strthuộc tính trên chuỗi.

'boolean' giống như 'bool' numpy nhưng nó cũng hỗ trợ dữ liệu bị thiếu.

Đọc tài liệu tham khảo đầy đủ ở đây:

Pandas dtype tham khảo

Gotchas, hãy cẩn thận, ghi chú

Cài đặt dtype=objectsẽ tắt cảnh báo ở trên, nhưng sẽ không làm cho bộ nhớ hiệu quả hơn, chỉ xử lý hiệu quả nếu có bất cứ điều gì.

Cài đặt dtype=unicodesẽ không làm bất cứ điều gì, kể từ khi numpy, a unicodeđược biểu diễn dưới dạng object.

Sử dụng bộ chuyển đổi

@sparrow chỉ ra chính xác việc sử dụng bộ chuyển đổi để tránh gấu trúc nổ tung khi gặp 'foobar'trong một cột được chỉ định là int. Tôi muốn thêm rằng các bộ chuyển đổi thực sự nặng và không hiệu quả để sử dụng trong gấu trúc và nên được sử dụng như là phương sách cuối cùng. Điều này là do quá trình read_csv là một quá trình duy nhất.

Các tệp CSV có thể được xử lý theo từng dòng và do đó có thể được xử lý song song bằng nhiều bộ chuyển đổi hiệu quả hơn bằng cách cắt tệp thành các phân đoạn và chạy nhiều quy trình, điều mà gấu trúc không hỗ trợ. Nhưng đây là một câu chuyện khác.


6
Vì vậy, do việc thiết lập một dtype=objectbộ nhớ không hiệu quả hơn, có lý do nào để gây rối với nó ngoài việc loại bỏ lỗi không?
zthomas.nc

6
@ zthomas.nc vâng, Pandas không cần bận tâm kiểm tra những gì trong cột. Về mặt lý thuyết tiết kiệm một số bộ nhớ trong khi tải (nhưng không có gì sau khi tải xong) và về mặt lý thuyết là lưu một số chu kỳ cpu (mà bạn sẽ không nhận thấy vì đĩa I / O sẽ là nút cổ chai.
Firelynx

5
"Điều đáng chú ý là nếu dòng cuối cùng trong tệp sẽ có" foobar "được ghi trong cột user_id, quá trình tải sẽ bị sập nếu dtype ở trên được chỉ định." Có một số tùy chọn "ép buộc" có thể được sử dụng để vứt bỏ hàng này thay vì sụp đổ?
chim sẻ

5
@sparrow có thể có, nhưng lần trước tôi sử dụng nó có lỗi. Nó có thể được sửa trong phiên bản mới nhất của gấu trúc. error_bad_lines=False, warn_bad_lines=Truenên làm thủ thuật. Tài liệu nói rằng nó chỉ hợp lệ với trình phân tích cú pháp C. Nó cũng cho biết trình phân tích cú pháp mặc định là Không làm cho khó biết cái nào là mặc định.
Firelynx

5
@nealmcb Bạn có thể đọc dataframe với nrows=100tư cách là một đối số và sau đó làm df.dtypesđể xem các dtypes bạn nhận được. Tuy nhiên, khi đọc toàn bộ khung dữ liệu với các kiểu này, hãy chắc chắn thực hiện try/exceptđể bạn có thể đoán được các lỗi dtype bị lỗi. Dữ liệu bị bẩn bạn biết đấy.
Firelynx

50

Thử:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Theo tài liệu về gấu trúc:

dtype: Nhập tên hoặc dict của cột -> type

Đối với low_memory, nó đúng theo mặc định và chưa được ghi lại. Tôi không nghĩ rằng nó có liên quan mặc dù. Thông báo lỗi là chung chung, vì vậy dù sao bạn cũng không cần phải gây rối với low_memory. Hy vọng điều này sẽ giúp và cho tôi biết nếu bạn có vấn đề hơn nữa


1
Thêm dtype=unicodesản xuất : NameError: name 'unicode' is not defined. Nhưng đặt unicodedấu ngoặc kép (như trong 'unicode') dường như hoạt động!
sedeh

5
@sedeh Bạn có thể chỉ định dtypes là loại python hoặc as numpy.dtype('unicode'). Khi bạn cung cấp cho tùy chọn dtype một chuỗi, nó sẽ cố gắng truyền nó qua numpy.dtype()nhà máy theo mặc định. Xác định 'unicode'thực sự sẽ không làm bất cứ điều gì, unicodes chỉ bị u ám objects. Bạn sẽ nhận đượcdtype='object'
Firelynx

43
df = pd.read_csv('somefile.csv', low_memory=False)

Điều này sẽ giải quyết vấn đề. Tôi đã nhận được chính xác lỗi tương tự, khi đọc 1,8 triệu hàng từ CSV.


51
Điều này làm im lặng lỗi, nhưng thực tế không thay đổi gì khác.
Firelynx

2
Tôi gặp vấn đề tương tự khi chạy tệp dữ liệu 1.5gb
Sitz Blogz

18

Như Firelynx đã đề cập trước đó nếu dtype được chỉ định rõ ràng và có dữ liệu hỗn hợp không tương thích với dtype đó thì tải sẽ bị sập. Tôi đã sử dụng một trình chuyển đổi như thế này như một cách giải quyết để thay đổi các giá trị với kiểu dữ liệu không tương thích để dữ liệu vẫn có thể được tải.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})

2

Tôi gặp vấn đề tương tự với tệp ~ 400MB. Thiết lập low_memory=Falseđã lừa tôi. Trước tiên hãy thực hiện những điều đơn giản, tôi sẽ kiểm tra xem khung dữ liệu của bạn không lớn hơn bộ nhớ hệ thống, khởi động lại, xóa RAM trước khi tiếp tục. Nếu bạn vẫn gặp phải lỗi, đáng để đảm bảo rằng .csvtệp của bạn vẫn ổn, hãy xem nhanh trong Excel và đảm bảo không có lỗi rõ ràng. Dữ liệu gốc bị hỏng có thể tàn phá ...


1

Tôi đã phải đối mặt với một vấn đề tương tự khi xử lý một tệp csv lớn (6 triệu hàng). Tôi có ba vấn đề: 1. tệp chứa các ký tự lạ (đã sửa bằng mã hóa) 2. kiểu dữ liệu không được chỉ định (đã sửa bằng thuộc tính dtype) 3. Sử dụng ở trên tôi vẫn gặp phải một vấn đề liên quan đến file_format không thể được xác định dựa trên tên tệp (cố định bằng cách sử dụng thử .. ngoại trừ ..)

df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                 names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                 dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})

try:
    df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
except:
    df['file_format'] = ''

-1

Nó hoạt động với tôi low_memory = Falsetrong khi nhập DataFrame. Đó là tất cả những thay đổi có hiệu quả với tôi:

df = pd.read_csv('export4_16.csv',low_memory=False)
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.