2014-07-15 35 views
6

Khi tôi cố nhập tệp csv vào gấu trúc khung (0.13.1) bỏ qua tham số dtype. Có cách nào để ngăn chặn gấu trúc tự mình suy ra loại dữ liệu không?Pandas read_csv bỏ qua dtypes cột khi tôi bỏ qua skip_footer arg

Tôi đang hợp nhất một số tệp CSV và đôi khi khách hàng chứa các chữ cái và nhập gấu trúc làm chuỗi. Khi tôi cố gắng hợp nhất hai datafram tôi nhận được một lỗi vì tôi đang cố gắng hợp nhất hai loại khác nhau. Tôi cần mọi thứ được lưu trữ dưới dạng chuỗi. đoạn mã

dữ liệu:

|WAREHOUSE|ERROR|CUSTOMER|ORDER NO| 
|---------|-----|--------|--------| 
|3615  |  |03106 |253734 | 
|3615  |  |03156 |290550 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 
|3615  |  |03175 |262207 | 

nhập dòng:

df = pd.read_csv("SomeFile.csv", 
       header=1, 
       skip_footer=1, 
       usecols=[2, 3], 
       dtype={'ORDER NO': str, 'CUSTOMER': str}) 

df.dtypes đầu ra này:

ORDER NO int64 
CUSTOMER int64 
dtype: object 
+0

Tôi đang sử dụng dtype như được đề xuất trong câu trả lời ở đó. Nó không giải quyết được vấn đề. – Ripster

+2

0.13.1 không tiết lộ rằng bạn đang quay trở lại trình phân tích cú pháp python vì '' usecols'' tôi nghĩ. và nó âm thầm phớt lờ '' dtype''. Hãy thử sử dụng 0.14.0 nó sẽ a) làm việc IIRC, b) sẽ cảnh báo khi điều này xảy ra (bạn có thể thử buộc động cơ với '' engine = 'c''', tại thời điểm đó tôi nghĩ rằng nó sẽ khiếu nại (ngay cả trong 0,13 .1) – Jeff

+0

0.13.1 không phàn nàn ngay cả với 'engine = 'c'' rõ ràng. Tôi cập nhật lên 0.14.1 và nó vẫn không hoạt động nhưng bạn đúng về cảnh báo tại sao.'ValueError: Quay trở lại động cơ 'python' vì động cơ 'c' không hỗ trợ skip_footer, nhưng điều này khiến 'dtype' bị bỏ qua vì nó không được hỗ trợ bởi động cơ 'python'. (Lưu ý tùy chọn 'chuyển đổi' cung cấp chức năng tương tự.) ' – Ripster

Trả lời

15

Pandas 0.13.1 âm thầm bỏ qua đối số dtypec engine không hỗ trợ skip_footer. Điều này khiến Pandas rơi trở lại python engine không hỗ trợ dtype.

Giải pháp? Sử dụng converters

df = pd.read_csv('SomeFile.csv', 
       header=1, 
       skip_footer=1, 
       usecols=[2, 3], 
       converters={'CUSTOMER': str, 'ORDER NO': str}, 
       engine='python') 

Output:

In [1]: df.dtypes 
Out[2]: 
CUSTOMER object 
ORDER NO object 
dtype: object 

In [3]: type(df['CUSTOMER'][0]) 
Out[4]: str 

In [5]: df.head() 
Out[6]: 
    CUSTOMER ORDER NO 
0 03106 253734 
1 03156 290550 
2 03175 262207 
3 03175 262207 
4 03175 262207 

Leading 0 từ tập tin gốc được lưu giữ và tất cả dữ liệu được lưu trữ như dây đàn.

6

Thật không may khi sử dụng trình chuyển đổi hoặc phiên bản gấu trúc mới hơn không giải quyết được vấn đề chung chung hơn bao giờ cũng đảm bảo rằng read_csv không suy ra float64 dtype. Với gấu trúc 0.15.2, ví dụ sau, với CSV chứa số nguyên theo ký hiệu thập lục phân với các mục NULL, cho thấy sử dụng trình biến đổi cho tên ngụ ý chúng nên được sử dụng để can thiệp vào đặc tả dtype.

In [1]: df = pd.DataFrame(dict(a = ["0xff", "0xfe"], b = ["0xfd", None], c = [None, "0xfc"], d = [None, None])) 
In [2]: df.to_csv("H:/tmp.csv", index = False) 
In [3]: ef = pd.read_csv("H:/tmp.csv", dtype = {c: object for c in "abcd"}, converters = {c: lambda x: None if x == "" else int(x, 16) for c in "abcd"}) 
In [4]: ef.dtypes.map(lambda x: x) 
Out[4]: 
a  int64 
b float64 
c float64 
d  object 
dtype: object 

Dtype được chỉ định của đối tượng chỉ được tôn trọng cho cột tất cả NULL. Trong trường hợp này, các giá trị float64 chỉ có thể được chuyển đổi thành các số nguyên, nhưng theo nguyên lý lỗ chim bồ câu, không phải tất cả các số nguyên 64 bit đều có thể được biểu diễn dưới dạng float64.

Giải pháp tốt nhất mà tôi đã tìm thấy cho trường hợp tổng quát này là để gấu trúc đọc các cột có khả năng có vấn đề như chuỗi, như đã được đề cập, sau đó chuyển đổi slice với các giá trị cần chuyển đổi (và không ánh xạ chuyển đổi trên cột, vì điều đó một lần nữa sẽ dẫn đến một suy luận dtype = float64 tự động).

In [5]: ff = pd.read_csv("H:/tmp.csv", dtype = {c: object for c in "bc"}, converters = {c: lambda x: None if x == "" else int(x, 16) for c in "ad"}) 
In [6]: ff.dtypes 
Out[6]: 
a  int64 
b object 
c object 
d object 
dtype: object 
In [7]: for c in "bc": 
    .....:  ff.loc[~pd.isnull(ff[c]), c] = ff[c][~pd.isnull(ff[c])].map(lambda x: int(x, 16)) 
    .....: 
In [8]: ff.dtypes 
Out[8]: 
a  int64 
b object 
c object 
d object 
dtype: object 
In [9]: [(ff[c][i], type(ff[c][i])) for c in ff.columns for i in ff.index] 
Out[9]: 
[(255, numpy.int64), 
(254, numpy.int64), 
(253L, long), 
(nan, float), 
(nan, float), 
(252L, long), 
(None, NoneType), 
(None, NoneType)] 

Theo như tôi đã có thể xác định, ít nhất là lên phiên bản 0,15,2 thì không có cách nào để tránh xử lý sau chuỗi giá trị trong các tình huống như thế này.