float64 với gấu trúc to_csv


88

Tôi đang đọc một CSV có số thực như sau:

Bob,0.085
Alice,0.005

Và nhập vào khung dữ liệu và ghi khung dữ liệu này vào một nơi mới

df = pd.read_csv(orig)
df.to_csv(pandasfile)

Bây giờ điều này pandasfilecó:

Bob,0.085000000000000006
Alice,0.0050000000000000001

Sao vậy? có lẽ tôi phải ép kiểu khác như float32 hay gì đó?

Tôi đang sử dụng gấu trúc 0.9.0numpy 1.6.2 .


26
Chào mừng bạn đến với số dấu phẩy động.
Ignacio Vazquez-Abrams


1
Tôi đã tạo một vấn đề để kiểm tra chi tiết hơn một chút tại đây: github.com/pydata/pandas/issues/2069 CHỈNH SỬA: Nếu bạn có thể, vui lòng đặt bản sao độc lập của vấn đề trên vấn đề GitHub. Tôi không thể tái tạo nó.
Wes McKinney

Câu trả lời:


165

Như đã đề cập trong các ý kiến, nó là một vấn đề dấu chấm động chung.

Tuy nhiên, bạn có thể sử dụng float_formattừ khóa của to_csvđể ẩn nó:

df.to_csv('pandasfile.csv', float_format='%.3f')

hoặc, nếu bạn không muốn 0,0001 được làm tròn thành 0:

df.to_csv('pandasfile.csv', float_format='%g')

sẽ cung cấp cho bạn:

Bob,0.085
Alice,0.005

trong tệp đầu ra của bạn.

Để biết giải thích về %g, hãy xem Ngôn ngữ thu nhỏ đặc tả định dạng .


Tôi đã nhận ra lỗiTypeError: __init__() got an unexpected keyword argument 'float_format'
wander95

Nếu ai đó gặp lỗi tương tự như @ wander95, có lẽ bạn cần cập nhật pandaslên phiên bản mới hơn.
driftcatcher

10

CẬP NHẬT: Câu trả lời là chính xác tại thời điểm viết và độ chính xác dấu phẩy động vẫn không phải là thứ bạn nhận được theo mặc định với to_csv / read_csv (cân bằng hiệu suất chính xác; mặc định ưu tiên hiệu suất).

Ngày nay có những float_formatlập luận có sẵn chopandas.DataFrame.to_csvcác float_precisionlập luận có sẵn chopandas.from_csv .

Bản gốc vẫn đáng đọc để nắm rõ hơn vấn đề.


Đó là một lỗi ở gấu trúc, không chỉ trong hàm "to_csv", mà cả trong "read_csv". Nó không phải là một vấn đề chung chung về dấu phẩy động, mặc dù đúng là số học dấu phẩy động là một môn học đòi hỏi sự quan tâm của người lập trình. Bài viết dưới đây làm rõ một chút về chủ đề này:

http://docs.python.org/2/tutorial/floatingpoint.html

Một lớp lót cổ điển cho thấy "vấn đề" là ...

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

... mà không hiển thị 0,3 như người ta mong đợi. Mặt khác, nếu bạn xử lý phép tính bằng số học điểm cố định và chỉ ở bước cuối cùng bạn sử dụng số học dấu phẩy động , nó sẽ hoạt động như bạn mong đợi. Xem cái này:

>>> (1 + 1 + 1)  * 1.0 / 10
0.3

Nếu bạn thực sự cần giải quyết vấn đề này, tôi khuyên bạn nên tạo một tệp CSV khác chứa tất cả các số liệu dưới dạng số nguyên, chẳng hạn như nhân với 100, 1000 hoặc hệ số khác, điều này thực sự thuận tiện. Bên trong ứng dụng của bạn, hãy đọc tệp CSV như bình thường và bạn sẽ lấy lại các số nguyên đó. Sau đó chuyển các giá trị đó thành dấu phẩy động, chia cho cùng một hệ số mà bạn đã nhân trước đó.

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.