Hướng dẫn for row in rows python - cho hàng trong hàng python

Cách lặp lại trên các hàng trong khung dữ liệu trong gấu trúc

Trả lời: Đừng*!

Lặp đi lặp lại trong gấu trúc là một loại chống lại và là điều bạn chỉ nên làm khi bạn đã cạn kiệt mọi lựa chọn khác. Bạn không nên sử dụng bất kỳ chức năng nào với "iter" trong tên của nó với hơn một vài nghìn hàng nếu không bạn sẽ phải làm quen với rất nhiều sự chờ đợi.lot of waiting.

Bạn có muốn in DataFrame không? Sử dụng DataFrame.to_string().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):

  1. Vector hóa
  2. Thói quen Cython
  3. Danh sách toàn diện (Vanilla for Loop)
  4. DataFrame.apply(): i) & nbsp; giảm có thể được thực hiện ở Cython, ii) Lặp lại trong không gian Python: i)  Reductions that can be performed in Cython, ii) Iteration in Python space
  5. DataFrame.itertuples()iteritems() and iteritems()
  6. DataFrame.iterrows()

iterrowsitertuples (cả hai đều nhận được nhiều phiếu bầu trong câu trả lời cho câu hỏi này) nên được sử dụng trong những trường hợp rất hiếm, chẳng hạn như tạo các đối tượng hàng/đặt tên để xử lý tuần tự, đây thực sự là điều duy nhất các chức năng này hữu ích.

Kháng cáo lên thẩm quyền

Trang tài liệu về Lặp lại có một hộp cảnh báo màu đỏ khổng lồ cho biết:

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 bằng tay trên 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 "đừng". iter0 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 hỏi hay hơn. Tôi sẽ thừa nhận rằng có những trường hợp không thể tránh được sự lặp lại (ví dụ: một số hoạt động trong đó kết quả phụ thuộc vào giá trị được tính toán cho hàng trước). Tuy nhiên, nó cần 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 lại hay không, có lẽ bạn không. Tái bút: Để biết thêm về lý do của tôi để viết câu trả lời này, bỏ qua phía dưới.


Nhanh hơn vòng lặp: vector hóa, cython

Một số lượng tốt các hoạt động và tính toán cơ bản được "vector hóa" bởi gấu trúc (thông qua Numpy hoặc thông qua các chức năng 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 (như xoay vòng), tham gia và hoạt động nhóm. Nhìn qua tài liệu về chức năng cơ bản cần thiết để tìm 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, hãy thoải mái viết của riêng bạn bằng cách sử dụng các tiện ích mở rộng Cython tùy chỉnh.


Điều tốt nhất tiếp theo: Liệt kê toàn diện*

Danh sách các toàn bộ phải là cổng gọi tiếp theo của bạn nếu 1) không có giải pháp vector hóa, 2) Hiệu suất là quan trọng, nhưng không đủ quan trọng để vượt qua sự rắc rối của việc cythonizing mã của bạn và 3) bạn đang cố gắng thực hiện chuyển đổi theo chiều thành phần tử trên mã của bạn. Có một lượng tốt bằng chứng cho thấy rằng sự hiểu biết 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 gọn logic doanh nghiệp của mình thành một chức năng, bạn có thể sử dụng danh sách hiểu biết 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 mã python thô.

Hãy cẩn thận

Danh sách các tính toán cho rằng dữ liệu của bạn dễ làm việc - điều đó có nghĩa là các loại dữ liệu của bạn phù hợp và bạn không có NAN, nhưng điều này không thể luôn luôn được đảm bảo.

  1. Cái đầu tiên rõ ràng hơn, nhưng khi xử lý NAN, thích các phương pháp gấu trúc được xây dựng nếu chúng tồn tại (vì chúng có logic xử lý trường hợp góc tốt hơn nhiều) hoặc đảm bảo logic kinh doanh của bạn bao gồm logic xử lý NAN phù hợp.
  2. Khi xử lý các loại dữ liệu hỗn hợp, bạn nên lặp lại trên iter1 thay vì iter2 vì loại sau này sẽ tăng dữ liệu theo loại phổ biến nhất. Ví dụ nếu A là số và B là chuỗi, iter3 sẽ chuyển toàn bộ mảng thành chuỗi, có thể không phải là thứ bạn muốn. May mắn thay iter4Ping 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.

*Số dặm của bạn có thể thay đổi vì những lý do được nêu trong phần Caveats ở trên.Caveats section above.


Một ví dụ rõ ràng

Chúng ta hãy chứng minh sự khác biệt với một ví dụ đơn giản về việc thêm hai cột gấu trúc iter5. Đây là một hoạt động có thể điều trị được, vì vậy sẽ dễ dàng đối chiếu hiệu suất của các phương pháp được thảo luận ở trên.

Hướng dẫn for row in rows python - cho hàng trong hàng python

Mã điểm chuẩn, để bạn tham khảo. Dòng ở phía dưới đo một hàm được viết bằng numpandas, một phong cách của gấu trúc pha trộn rất nhiều với numpy để vắt kiệt hiệu suất tối đa. Viết mã Numpandas nên tránh trừ khi bạn biết bạn đang làm gì. Bám sát API nơi bạn có thể (tức là, thích iter6 hơn iter7).

Tuy nhiên, tôi nên đề cập rằng nó không phải lúc nào cũng 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à kiểm tra 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 trên một cách giải quyết.


Ý kiến ​​cá nhân của tôi *

Hầu hết các phân tích được thực hiện trên các lựa chọn thay thế khác nhau cho gia đình ITER đã trải qua lăng kính hiệu suất. Tuy nhiên, trong hầu hết các tình huống, bạn thường sẽ làm việc trên một bộ dữ liệu có kích thước hợp lý (không có gì ngoài vài nghìn hoặc 100k hàng) và hiệu suất sẽ đứng thứ hai sau tính đơn giản/khả năng đọc của giải pháp.

Đây là sở thích cá nhân của tôi khi chọn một phương pháp để sử dụng cho một vấn đề.

Cho người mới:

Vector hóa (khi có thể); iter8; Danh sách toàn diện; ________ 19/________ 6; DataFrame.to_string()1; Cython

Cho những người có kinh nghiệm hơn:

Vector hóa (khi có thể); iter8; Danh sách toàn diện; Cython; ________ 19/________ 6; DataFrame.to_string()1

Vectorization chiếm ưu thế là phương pháp thành ngữ nhất cho bất kỳ vấn đề nào có thể được vector hóa. Luôn luôn tìm cách vectorize! Khi nghi ngờ, hãy tham khảo các tài liệu hoặc xem xét Stack Overflow cho một câu hỏi hiện có về nhiệm vụ cụ thể của bạn.

Tôi có xu hướng tiếp tục về việc DataFrame.to_string()6 tệ đến mức nào trong rất nhiều bài viết của tôi, nhưng tôi thừa nhận rằng người mới bắt đầu sẽ dễ dàng quấn đầu họ xung quanh những gì nó đang làm. Ngoài ra, có khá nhiều trường hợp sử dụng cho DataFrame.to_string()6 đã giải thích trong bài đăng này của tôi.

Cython xếp hạng thấp hơn trong danh sách vì phải mất nhiều thời gian và nỗ lực hơn để thực hiện chính xác. Bạn thường sẽ không bao giờ cần phải viết mã với gấu trúc đòi hỏi mức độ hiệu suất này mà ngay cả việc hiểu danh sách cũng không thể thỏa mãn.

* Như với bất kỳ ý kiến ​​cá nhân, xin vui lòng lấy hàng đống muối!


Đọc thêm

  • 10 phút đến gấu trúc và chức năng cơ bản thiết yếu - các liên kết hữu ích giới thiệu cho bạn về gấu trúc và thư viện các chức năng vector hóa*/cythonized của nó.

  • Tăng cường hiệu suất - Một đoạn mồi từ tài liệu về tăng cường hoạt động của gấu trúc tiêu chuẩn

  • Có phải vòng lặp trong gấu trúc thực sự xấu? Khi nào tôi nên quan tâm? -Một bài viết chi tiết của tôi về sự hiểu biết danh sách và sự phù hợp của chúng cho các hoạt động khác nhau (chủ yếu là các hoạt động liên quan đến dữ liệu không phải là số lượng)

  • Khi nào tôi nên (không) muốn sử dụng gấu trúc áp dụng () trong mã của tôi? - DataFrame.to_string()6 chậm (nhưng không chậm như gia đình DataFrame.to_string()9. Tuy nhiên, có những tình huống mà người ta có thể (hoặc nên) coi DataFrame.to_string()6 là một sự thay thế nghiêm trọng, đặc biệt là trong một số hoạt động for1).

* Các phương thức chuỗi pandas được "vector hóa" theo nghĩa chúng được chỉ định trên chuỗi nhưng hoạt động trên mỗi 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 rất 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 tôi nhận thấy từ người dùng mới là đặt câu hỏi về biểu mẫu "Làm thế nào tôi có thể lặp lại DF của mình để làm X?". Hiển thị mã gọi DataFrame.to_string()1 trong khi thực hiện một cái gì đó bên trong vòng lặp for. Đây là lý do tại sao. Một người dùng mới đến thư viện, người chưa được giới thiệu về khái niệm vector hóa có thể sẽ 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 điều gì đó. Không biết cách lặp lại một khung dữ liệu, đ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 nói với họ cách, và họ nhắm mắt và chạy mã này mà không bao giờ đặt câu hỏi trước khi lặp đi lặp lại có 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 việc 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ố gắng bắt đầu một cuộc chiến lặp lại so với vectorization, nhưng tôi muốn người dùng mới được thông báo khi phát triển các giải pháp cho các vấn đề của họ với thư viện này.