Làm cách nào để lặp lại qua các hàng trong DataFrame trong Pandas?
Trả lời: KHÔNG * !
Lặp lại trong gấu trúc là một mô hình chống, và là điều bạn chỉ nên làm khi bạn đã hết tất cả các lựa chọn khác. Bạn không nên sử dụng bất kỳ chức năng nào có " iter
" trong tên của nó trong hơn một vài nghìn hàng hoặc bạn sẽ phải làm quen với rất nhiều sự chờ đợi.
Bạn có muốn in DataFrame không? Sử dụng DataFrame.to_string()
.
Bạn có muốn tính toán một cái gì đó? Trong trường hợp đó, tìm kiếm các phương thức theo thứ tự này (danh sách được sửa đổi từ đây ):
- Vector hóa
- Thói quen của Cython
- Danh sách hiểu (
for
vòng vanilla )
DataFrame.apply()
: i) Việc giảm có thể được thực hiện trong cython, ii) Lặp lại trong không gian python
DataFrame.itertuples()
và iteritems()
DataFrame.iterrows()
iterrows
và itertuples
(cả hai nhận được nhiều phiếu trong câu trả lời cho câu hỏi này) nên được sử dụng trong các trường hợp rất hiếm, chẳng hạn như tạo các đối tượng hàng / bảng tên để xử lý tuần tự, đây thực sự là điều duy nhất các hàm này hữu ích.
Khiếu nại với chính quyền
Trang tài liệu về Lặp lại có một hộp cảnh báo màu đỏ rất lớn có nội dung:
Lặp lại thông qua các đối tượng gấu trúc nói chung là chậm. Trong nhiều trường hợp, việc lặp lại thủ công qua các hàng là không cần thiết [...].
* Nó thực sự phức tạp hơn một chút so với "không". df.iterrows()
là câu trả lời chính xác cho câu hỏi này, nhưng "vectorize ops của bạn" là câu trả lời tốt hơn. Tôi sẽ thừa nhận rằng có những trường hợp không thể tránh được việc lặp lại (ví dụ: một số thao tác trong đó kết quả phụ thuộc vào giá trị được tính cho hàng trước đó). Tuy nhiên, phải mất một số quen thuộc với thư viện để biết khi nào. Nếu bạn không chắc chắn liệu bạn có cần một giải pháp lặp đi lặp lại hay không, có lẽ bạn không nên. PS: Để biết thêm về lý do của tôi khi viết câu trả lời này, hãy bỏ qua đến tận cùng.
Một số lượng lớn các hoạt động và tính toán cơ bản được "véc tơ" bởi gấu trúc (thông qua NumPy hoặc thông qua các hàm Cythonized). Điều này bao gồm số học, so sánh, giảm (hầu hết), định hình lại (chẳng hạn như xoay vòng), tham gia và hoạt động nhóm. Xem qua các tài liệu về Essential Basic Functionality để tìm ra một phương pháp vector hóa phù hợp cho vấn đề của bạn.
Nếu không tồn tại, vui lòng tự viết bằng các tiện ích mở rộng cython tùy chỉnh .
Việc hiểu danh sách sẽ là cổng gọi tiếp theo của bạn nếu 1) không có giải pháp véc tơ khả dụng, 2) hiệu suất rất quan trọng, nhưng không đủ quan trọng để vượt qua rắc rối của việc mã hóa mã của bạn và 3) bạn đang cố gắng thực hiện chuyển đổi theo yếu tố trên mã của bạn. Có một lượng bằng chứng tốt để đề xuất rằng việc hiểu danh sách là đủ nhanh (và thậm chí đôi khi nhanh hơn) cho nhiều nhiệm vụ gấu trúc thông thường.
Công thức rất đơn giản,
# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]
Nếu bạn có thể gói logic logic kinh doanh của mình vào một hàm, bạn có thể sử dụng một cách hiểu danh sách gọi nó. Bạn có thể làm cho những thứ phức tạp tùy ý hoạt động thông qua sự đơn giản và tốc độ của trăn thô.
Việc
hiểu danh sách Caveats cho rằng dữ liệu của bạn dễ làm việc - điều đó có nghĩa là loại dữ liệu của bạn nhất quán và bạn không có NaN, nhưng điều này không thể luôn được đảm bảo.
- Cách thứ nhất thì rõ ràng hơn, nhưng khi giao dịch với NaN, hãy thích các phương pháp gấu trúc dựng sẵn nếu chúng tồn tại (vì chúng có logic xử lý tình huống góc tốt hơn nhiều) hoặc đảm bảo logic nghiệp vụ của bạn bao gồm logic xử lý NaN thích hợp.
- Khi xử lý các loại dữ liệu hỗn hợp, bạn nên lặp đi lặp lại
zip(df['A'], df['B'], ...)
thay vì df[['A', 'B']].to_numpy()
kiểu sau sẽ ngầm định dữ liệu thành loại phổ biến nhất. Ví dụ nếu A là số và B là chuỗi, to_numpy()
sẽ truyền toàn bộ mảng thành chuỗi, đây có thể không phải là điều bạn muốn. May mắn là zip
ping các cột của bạn với nhau là cách giải quyết đơn giản nhất cho việc này.
* YMMV vì những lý do được nêu trong phần Caveats ở trên.
Một ví dụ rõ ràng
Hãy chứng minh sự khác biệt bằng một ví dụ đơn giản về việc thêm hai cột gấu trúc A + B
. Đây là một toán hạng có thể vector hóa, vì vậy nó sẽ dễ dàng tương phản hiệu suất của các phương pháp được thảo luận ở trên.
Mã điểm chuẩn, để bạn tham khảo.
Tôi nên đề cập, tuy nhiên, nó không phải lúc nào cũng bị cắt và khô. Đôi khi, câu trả lời cho "phương pháp tốt nhất cho hoạt động" là "nó phụ thuộc vào dữ liệu của bạn". Lời khuyên của tôi là thử nghiệm các cách tiếp cận khác nhau trên dữ liệu của bạn trước khi giải quyết một.
Đọc thêm
* Các phương thức chuỗi Pandas được "vector hóa" theo nghĩa là chúng được chỉ định trên chuỗi nhưng hoạt động trên từng phần tử. Các cơ chế cơ bản vẫn còn lặp đi lặp lại, bởi vì các hoạt động chuỗi vốn đã khó để vector hóa.
Tại sao tôi viết câu trả lời này
Một xu hướng phổ biến mà tôi nhận thấy từ những người dùng mới là đặt câu hỏi theo mẫu "làm thế nào tôi có thể lặp lại trên df của mình để làm X?". Hiển thị mã gọi iterrows()
trong khi thực hiện một cái gì đó bên trong một vòng lặp for. Đây là lý do tại sao. Một người dùng mới vào thư viện chưa được giới thiệu về khái niệm vector hóa sẽ có khả năng hình dung mã giải quyết vấn đề của họ khi lặp lại dữ liệu của họ để làm gì đó. Không biết làm thế nào để lặp lại trên DataFrame, điều đầu tiên họ làm là Google nó và kết thúc ở đây, tại câu hỏi này. Sau đó, họ thấy câu trả lời được chấp nhận cho họ biết làm thế nào, và họ nhắm mắt lại và chạy mã này mà không bao giờ đặt câu hỏi đầu tiên nếu việc lặp lại không phải là điều đúng đắn.
Mục đích của câu trả lời này là giúp người dùng mới hiểu rằng lặp đi lặp lại không nhất thiết là giải pháp cho mọi vấn đề và các giải pháp tốt hơn, nhanh hơn và thành ngữ hơn có thể tồn tại và đáng để đầu tư thời gian để khám phá chúng. Tôi không cố bắt đầu cuộc chiến lặp lại so với vector hóa, nhưng tôi muốn người dùng mới được thông báo khi phát triển giải pháp cho các vấn đề của họ với thư viện này.