Các chuỗi trong DataFrame, nhưng dtype là đối tượng


96

Tại sao Pandas nói với tôi rằng tôi có các đối tượng, mặc dù mọi mục trong cột đã chọn là một chuỗi - ngay cả sau khi chuyển đổi rõ ràng.

Đây là DataFrame của tôi:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id            56992  non-null values
attr1         56992  non-null values
attr2         56992  non-null values
attr3         56992  non-null values
attr4         56992  non-null values
attr5         56992  non-null values
attr6         56992  non-null values
dtypes: int64(2), object(5)

Năm trong số đó là dtype object. Tôi chuyển đổi rõ ràng các đối tượng đó thành chuỗi:

for c in df.columns:
    if df[c].dtype == object:
        print "convert ", df[c].name, " to string"
        df[c] = df[c].astype(str)

Sau đó, df["attr2"]vẫn có dtype object, mặc dù type(df["attr2"].ix[0]tiết lộ str, đó là chính xác.

Gấu trúc phân biệt giữa int64float64object. Logic đằng sau nó là gì khi không có dtype str? Tại sao một strđược bao phủ bởi object?


Đến đây vì liên kết không thành công do 'loại đối tượng' mặc dù mọi chuỗi "là"
Monica Heddneck

Câu trả lời:


145

Đối tượng dtype đến từ NumPy, nó mô tả kiểu phần tử trong một ndarray. Mọi phần tử trong ndarray phải có cùng kích thước tính bằng byte. Đối với int64 và float64, chúng là 8 byte. Nhưng đối với chuỗi, độ dài của chuỗi không cố định. Vì vậy, thay vì lưu trực tiếp các byte chuỗi trong ndarray, Pandas sử dụng object ndarray để lưu các con trỏ đến các đối tượng, bởi vì loại dtype của loại ndarray này là object.

Đây là một ví dụ:

  • mảng int64 chứa 4 giá trị int64.
  • mảng đối tượng chứa 4 con trỏ đến 3 đối tượng chuỗi.

nhập mô tả hình ảnh ở đây


3
Tuy nhiên, lưu ý rằng việc có các cột kiểu 'đối tượng' có tác động lớn đến hiệu suất của các hoạt động đọc / ghi
DataFrame

Tôi có thể nhận được kiểu dữ liệu được trả về dưới dạng chuỗi, bằng cách nào đó. Tôi biết tôi luôn có thể sử dụng loại, nhưng nó có thể để xảy ra rằng nó là nan (df [ "cột"] iloc [0].)
user1953366

7

Câu trả lời được chấp nhận là tốt. Chỉ muốn cung cấp một câu trả lời tham khảo tài liệu . Tài liệu cho biết:

Pandas sử dụng đối tượng dtype để lưu trữ chuỗi.

Như bình luận hàng đầu nói "Đừng lo lắng về nó; nó phải như thế này." (Mặc dù câu trả lời được chấp nhận đã làm rất tốt việc giải thích "tại sao"; các chuỗi có độ dài thay đổi)

Nhưng đối với chuỗi, độ dài của chuỗi không cố định.


Tại sao tôi cần chuyển đổi mọi cột tôi chuyển thành scipy hoặc sklearn astype (str) để nó chấp nhận nó? dường như ban đầu tôi có thể áp dụng điều đó cho tất cả các cột.
Tinkinc

Tôi không hiểu; @Tinkinc điều gì sẽ xảy ra nếu bạn không chuyển đổi cột thành chuỗi? Và câu trả lời này dường như là một cách thanh lịch để chuyển đổi tất cả các cộtastype(str) mặc dù tôi vẫn ngạc nhiên chuỗi chuyển đổi là cần thiết
The Red Pea

Tôi không thể fillna (0) tất cả các đối tượng trong nghỉ dataframe của tôi (1, nan) thay vì (1,0)
Tinkinc

Xin lỗi @Tinkinc tôi vẫn chưa hiểu; Tôi muốn trợ giúp, nhưng vấn đề của bạn nghe có vẻ phức tạp hơn nhận xét Stack Overflow. Cân nhắc đặt câu hỏi hoặc tham gia trò chuyện với tôi. (chỉ mời bạn)
The Red Pea

5

Câu trả lời của @ HYRY thật tuyệt. Tôi chỉ muốn cung cấp thêm một chút ngữ cảnh ..

Mảng dữ liệu được lưu trữ dưới dạng khối bộ nhớ liền kề , kích thước cố định . Sự kết hợp của các thuộc tính này với nhau là điều làm cho các mảng nhanh như chớp để truy cập dữ liệu. Ví dụ: hãy xem xét cách máy tính của bạn có thể lưu trữ một mảng các số nguyên 32 bit [3,0,1],.

nhập mô tả hình ảnh ở đây

Nếu bạn yêu cầu máy tính tìm nạp phần tử thứ 3 trong mảng, nó sẽ bắt đầu từ đầu và sau đó nhảy qua 64 bit để đến phần tử thứ 3. Biết chính xác bao nhiêu bit để nhảy qua là điều làm cho mảng nhanh chóng .

Bây giờ hãy xem xét trình tự của các chuỗi ['hello', 'i', 'am', 'a', 'banana']. Chuỗi là các đối tượng có kích thước khác nhau, vì vậy nếu bạn cố gắng lưu trữ chúng trong các khối bộ nhớ liền kề, nó sẽ trông như thế này.

nhập mô tả hình ảnh ở đây

Bây giờ máy tính của bạn không có cách nhanh chóng để truy cập một phần tử được yêu cầu ngẫu nhiên. Chìa khóa để khắc phục điều này là sử dụng con trỏ. Về cơ bản, lưu trữ mỗi chuỗi trong một số vị trí bộ nhớ ngẫu nhiên và điền vào mảng bằng địa chỉ bộ nhớ của mỗi chuỗi. (Địa chỉ bộ nhớ chỉ là số nguyên.) Vì vậy, bây giờ, mọi thứ trông như thế này

nhập mô tả hình ảnh ở đây

Bây giờ, nếu bạn yêu cầu máy tính của mình tìm nạp phần tử thứ 3, giống như trước đây, nó có thể nhảy qua 64 bit (giả sử địa chỉ bộ nhớ là số nguyên 32 bit) và sau đó thực hiện thêm một bước để tìm nạp chuỗi.

Thách thức đối với NumPy là không có gì đảm bảo các con trỏ thực sự trỏ đến chuỗi. Đó là lý do tại sao nó báo cáo loại dtype là 'đối tượng'.

Không biết xấu hổ sẽ cắm bài viết trên blog của riêng tôi , nơi tôi đã thảo luận về điều này ban đầu.



1

Kể từ phiên bản 1.0.0 (tháng 1 năm 2020), pandas đã được giới thiệu dưới dạng một tính năng thử nghiệm cung cấp hỗ trợ hạng nhất cho các loại chuỗi pandas.StringDtype.

Trong khi bạn vẫn sẽ được nhìn thấy objecttheo mặc định, loại mới có thể được sử dụng bằng cách xác định một dtypesố pd.StringDtypehoặc đơn giản là 'string':

>>> pd.Series(['abc', None, 'def'])
0     abc
1    None
2     def
dtype: object
>>> pd.Series(['abc', None, 'def'], dtype=pd.StringDtype())
0     abc
1    <NA>
2     def
dtype: string
>>> pd.Series(['abc', None, 'def']).astype('string')
0     abc
1    <NA>
2     def
dtype: string

2
Chưa sử dụng cái này .... Như họ đã nêu, The implementation may change without warning.có nghĩa là các bản cập nhật mới sẽ phá vỡ các chương trình cũ của bạn.
NoName

1
Tất cả phụ thuộc vào việc bạn sẽ sử dụng nó để làm gì. Nếu bạn muốn sử dụng nó trong một hệ thống sản xuất cần nâng cấp gói liên tục và khi lỗi API gây ra gánh nặng bảo trì không thể chấp nhận được, thì chắc chắn, hãy chú ý đến từ "thử nghiệm", nhưng nếu bạn đang sử dụng gấu trúc để thực hiện khám phá phân tích trong các kịch bản mà thời gian sống của nó không tăng thêm một ngày làm việc, thì những mối quan tâm đó sẽ chẳng có ý nghĩa gì đối với bạn.
fuglede

Kể từ Pandas 1.1, API dường như đã ổn định Tất cả các loại hiện có thể được chuyển đổi thành StringDtype .
D3f0
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.