Có nhiều lý do tại sao người ta có thể thích một chức năng apply
gia đình qua một vòng lặp for
, hoặc ngược lại.
Thứ nhất, for()
và apply()
, sapply()
thường sẽ nhanh như nhau nếu được thi hành chính xác. lapply()
hoạt động nhiều hơn trong mã được biên dịch trong nội bộ R so với các mã khác, vì vậy có thể nhanh hơn các hàm đó. Nó xuất hiện lợi thế tốc độ là lớn nhất khi hành động "looping" trên dữ liệu là một phần quan trọng của thời gian tính toán; trong nhiều lần sử dụng hàng ngày nói chung, bạn không có khả năng thu được nhiều từ số tiền lapply()
vốn nhanh hơn. Cuối cùng, tất cả những điều này sẽ được gọi là R chức năng để họ cần phải được giải thích và sau đó chạy.
for()
vòng lặp thường có thể dễ thực hiện hơn, đặc biệt nếu bạn đến từ nền tảng lập trình nơi vòng lặp phổ biến. Làm việc trong một vòng lặp có thể tự nhiên hơn là buộc tính toán lặp lại thành một trong các hàm gia đình apply
. Tuy nhiên, để sử dụng các vòngđúng cách, bạn cần thực hiện thêm một số công việc để thiết lập bộ nhớ và quản lý việc cắm đầu ra của vòng lặp lại với nhau. Các chức năng apply
làm điều này cho bạn một cách tự động. Ví dụ .:
IN <- runif(10)
OUT <- logical(length = length(IN))
for(i in IN) {
OUT[i] <- IN > 0.5
}
đó là một ngớ ngẩn dụ như >
là một nhà điều hành vectorised nhưng tôi muốn một cái gì đó để làm cho một điểm, cụ thể là bạn phải quản lý đầu ra. Điều chính là với các vòng for()
, bạn luôn luôn phân bổ đủ bộ nhớ để giữ đầu ra trước khi bạn bắt đầu vòng lặp. Nếu bạn không biết bạn sẽ cần bao nhiêu dung lượng lưu trữ, hãy phân bổ một lượng lưu trữ hợp lý và sau đó kiểm tra vòng lặp nếu bạn đã cạn kiệt bộ nhớ đó và sử dụng bộ nhớ lưu trữ lớn khác.
Lý do chính, trong suy nghĩ của tôi, khi sử dụng một trong các dòng chức năng apply
là để có mã dễ đọc hơn, thanh lịch hơn. Thay vì quản lý lưu trữ đầu ra và thiết lập vòng lặp (như được hiển thị ở trên), chúng ta có thể để R xử lý và yêu cầu R chạy một hàm trên các tập con dữ liệu của chúng ta.Tốc độ thường là không đưa vào quyết định, ít nhất là đối với tôi. Tôi sử dụng chức năng phù hợp với tình huống tốt nhất và sẽ dẫn đến mã đơn giản, dễ hiểu, vì tôi có nhiều khả năng lãng phí nhiều thời gian hơn tôi tiết kiệm bằng cách luôn chọn chức năng nhanh nhất nếu tôi không nhớ mã đó là gì làm một ngày hoặc một tuần hoặc nhiều hơn sau đó!
apply
gia đình tự vay cho hoạt động vô hướng hoặc vectơ. Vòng lặp for()
thường sẽ tự vay để thực hiện nhiều thao tác lặp lại sử dụng cùng một chỉ mục i
. Ví dụ: tôi đã viết mã sử dụng các vòng for()
để làm k - gấp hoặc xác thực chéo khởi động trên các đối tượng. Tôi có lẽ sẽ không bao giờ giải trí với một trong các gia đình apply
vì mỗi lần lặp CV cần nhiều thao tác, truy cập vào rất nhiều đối tượng trong khung hiện tại và điền vào một số đối tượng đầu ra giữ đầu ra của các lần lặp.
Đối với điểm cuối cùng, về việc tại sao lapply()
có thể có thể nhanh hơn mà for()
hoặc apply()
, bạn cần phải nhận ra rằng "loop" có thể được thực hiện trong mã R giải thích hoặc trong mã được biên dịch. Có, cả hai vẫn sẽ gọi các hàm R cần được giải thích, nhưng nếu bạn đang thực hiện lặp và gọi trực tiếp từ mã C đã biên dịch (ví dụ: lapply()
) thì đó là nơi hiệu suất có thể đến từ hơn apply()
. một vòng lặp for()
trong mã R thực tế. Xem nguồn cho apply()
để thấy rằng nó là một wrapper xung quanh một vòng for()
, và sau đó nhìn vào mã cho lapply()
, đó là:
> lapply
function (X, FUN, ...)
{
FUN <- match.fun(FUN)
if (!is.vector(X) || is.object(X))
X <- as.list(X)
.Internal(lapply(X, FUN))
}
<environment: namespace:base>
và bạn sẽ thấy lý do tại sao có thể có một sự khác biệt về tốc độ giữa lapply()
và for()
và các chức năng gia đình khác apply
. .Internal()
là một trong những cách gọi R được biên dịch mã C được sử dụng bởi chính R. Ngoài thao tác, và kiểm tra độ chính xác trên FUN
, toàn bộ tính toán được thực hiện bằng C, gọi hàm R FUN
. So sánh điều đó với nguồn cho apply()
.
Xem chủ đề này: http://stackoverflow.com/q/2275896/429846 –
Và điều này một: http://stackoverflow.com/q/5533246/210673 – Aaron
Ngoài ra còn có một lớn R bài viết Help Desk về điều này từ tháng 5 năm 2008: http://promberger.info/files/rnews-vectorvsloops2008.pdf – DrewConway