Truy cập tên chỉ mục lapply trong FUN


162

Có cách nào để lấy tên chỉ mục danh sách trong hàm lapply () của tôi không?

n = names(mylist)
lapply(mylist, function(list.elem) { cat("What is the name of this list element?\n" })

Tôi đã hỏi trước đây liệu có thể giữ các tên chỉ mục trong danh sách được trả về lapply () không , nhưng tôi vẫn không biết liệu có cách nào dễ dàng để tìm nạp từng tên thành phần bên trong hàm tùy chỉnh không. Tôi muốn tránh gọi chính mình bằng tên, tôi muốn lấy tên trong các tham số chức năng.


Có thêm một mẹo, với các thuộc tính. Xem tại đây: stackoverflow.com/questions/4164960/ , loại tương tự như những gì DWin có, nhưng khác nhau. :)
Roman Luštrik

Câu trả lời:


161

Thật không may, lapplychỉ cung cấp cho bạn các yếu tố của vectơ bạn vượt qua nó. Cách làm việc thông thường là truyền cho nó tên hoặc chỉ số của vectơ thay vì chính vectơ.

Nhưng lưu ý rằng bạn luôn có thể chuyển các đối số bổ sung cho hàm, vì vậy các công việc sau:

x <- list(a=11,b=12,c=13) # Changed to list to address concerns in commments
lapply(seq_along(x), function(y, n, i) { paste(n[[i]], y[[i]]) }, y=x, n=names(x))

Ở đây tôi sử dụng lapplycác chỉ số của x, nhưng cũng truyền vào xvà tên của x. Như bạn có thể thấy, thứ tự của các đối số hàm có thể là bất cứ thứ gì - lapplysẽ chuyển trong "phần tử" (ở đây là chỉ mục) cho đối số đầu tiên không được chỉ định trong số các đối số phụ. Trong trường hợp này, tôi chỉ định yn, vì vậy chỉ icòn lại ...

Mà sản xuất như sau:

[[1]]
[1] "a 11"

[[2]]
[1] "b 12"

[[3]]
[1] "c 13"

CẬP NHẬT Ví dụ đơn giản hơn, kết quả tương tự:

lapply(seq_along(x), function(i) paste(names(x)[[i]], x[[i]]))

Ở đây hàm sử dụng biến "toàn cầu" xvà trích xuất tên trong mỗi cuộc gọi.


Tham số 'i' được khởi tạo trong chức năng tùy chỉnh như thế nào?
Robert Kubrick

Có nó, vì vậy lapply () thực sự áp dụng cho các yếu tố được trả về bởi seq_along. Tôi đã bối rối vì các tham số chức năng tùy chỉnh được sắp xếp lại. Thông thường phần tử danh sách lặp là tham số đầu tiên.
Robert Kubrick

Cập nhật câu trả lời và thay đổi chức năng đầu tiên để sử dụng ythay vì xđể nó rõ ràng hơn (hy vọng) rằng hàm có thể gọi nó là đối số bất cứ điều gì. Cũng thay đổi giá trị vector thành 11,12,13.
Tommy

@RobertKubrick - Vâng, có lẽ tôi đã cố gắng thể hiện quá nhiều thứ cùng một lúc ... Bạn có thể đặt tên cho các đối số bất cứ điều gì và có chúng theo bất kỳ thứ tự nào.
Tommy

@DWin - Tôi nghĩ nó cũng đúng (và cũng áp dụng cho các danh sách) ;-) ... Nhưng vui lòng chứng minh tôi sai!
Tommy

48

Điều này về cơ bản sử dụng cách giải quyết tương tự như Tommy, nhưng với Map(), không cần phải truy cập các biến toàn cục lưu trữ tên của các thành phần danh sách.

> x <- list(a=11, b=12, c=13)
> Map(function(x, i) paste(i, x), x, names(x))
$a
[1] "a 11"

$b
[1] "b 12"

$c
[1] "c 13

Hoặc, nếu bạn thích mapply()

> mapply(function(x, i) paste(i, x), x, names(x))
     a      b      c 
"a 11" "b 12" "c 13"

Đây chắc chắn là giải pháp tốt nhất của bó.
emilBeBri

Khi sử dụng mapply(), hãy chú ý SIMPLIFYtùy chọn, mặc định là true. Trong trường hợp của tôi, điều đó làm cho toàn bộ điều thành một ma trận lớn khi tôi chỉ muốn áp dụng một danh sách đơn giản. Đặt nó thành F(bên trong mapply()) làm cho nó chạy như dự định.
JJ cho Minh bạch và Monica

39

CẬP NHẬT cho phiên bản R 3.2

Tuyên bố từ chối trách nhiệm: đây là một thủ thuật hacky và có thể ngừng hoạt động trong các phiên bản tiếp theo.

Bạn có thể lấy chỉ mục bằng cách này:

> lapply(list(a=10,b=20), function(x){parent.frame()$i[]})
$a
[1] 1

$b
[1] 2

Lưu ý: điều []này là bắt buộc để nó hoạt động, vì nó khiến R nghĩ rằng biểu tượng i(nằm trong khung đánh giá lapply) có thể có nhiều tham chiếu hơn, do đó kích hoạt sự trùng lặp lười biếng của nó. Không có nó, R sẽ không giữ các bản sao riêng biệt của i:

> lapply(list(a=10,b=20), function(x){parent.frame()$i})
$a
[1] 2

$b
[1] 2

Các thủ thuật kỳ lạ khác có thể được sử dụng, như function(x){parent.frame()$i+0}hoặc function(x){--parent.frame()$i}.

Hiệu suất tác động

Sự trùng lặp bắt buộc sẽ gây ra mất hiệu suất? Đúng! đây là điểm chuẩn:

> x <- as.list(seq_len(1e6))

> system.time( y <- lapply(x, function(x){parent.frame()$i[]}) )
user system elapsed
2.38 0.00 2.37
> system.time( y <- lapply(x, function(x){parent.frame()$i[]}) )
user system elapsed
2.45 0.00 2.45
> system.time( y <- lapply(x, function(x){parent.frame()$i[]}) )
user system elapsed
2.41 0.00 2.41
> y[[2]]
[1] 2

> system.time( y <- lapply(x, function(x){parent.frame()$i}) )
user system elapsed
1.92 0.00 1.93
> system.time( y <- lapply(x, function(x){parent.frame()$i}) )
user system elapsed
2.07 0.00 2.09
> system.time( y <- lapply(x, function(x){parent.frame()$i}) )
user system elapsed
1.89 0.00 1.89
> y[[2]]
[1] 1000000

Phần kết luận

Câu trả lời này chỉ cho thấy rằng bạn KHÔNG nên sử dụng điều này ... Không chỉ mã của bạn sẽ dễ đọc hơn nếu bạn tìm một giải pháp khác như Tommy ở trên và tương thích hơn với các bản phát hành trong tương lai, bạn cũng có nguy cơ mất tối ưu hóa mà nhóm nòng cốt đã làm việc chăm chỉ phát triển, xây dựng!


Thủ thuật của phiên bản cũ, không còn hoạt động:

> lapply(list(a=10,b=10,c=10), function(x)substitute(x)[[3]])

Kết quả:

$a
[1] 1

$b
[1] 2

$c
[1] 3

Giải thích: lapplytạo các lệnh gọi của biểu mẫu FUN(X[[1L]], ...), FUN(X[[2L]], ...)v.v ... Vì vậy, đối số mà nó truyền qua là X[[i]]vị trí icủa chỉ mục hiện tại trong vòng lặp. Nếu chúng tôi nhận được điều này trước khi nó được đánh giá (nghĩa là, nếu chúng tôi sử dụng substitute), chúng tôi sẽ nhận được biểu thức không được đánh giá X[[i]]. Đây là một lệnh gọi [[hàm, với các đối số X(ký hiệu) và i(một số nguyên). Vì vậy, substitute(x)[[3]]trả về chính xác số nguyên này.

Có chỉ mục, bạn có thể truy cập các tên một cách tầm thường, nếu bạn lưu nó trước như thế này:

L <- list(a=10,b=10,c=10)
n <- names(L)
lapply(L, function(x)n[substitute(x)[[3]]])

Kết quả:

$a
[1] "a"

$b
[1] "b"

$c
[1] "c"

Hoặc sử dụng thủ thuật thứ hai này :-)

lapply(list(a=10,b=10,c=10), function(x)names(eval(sys.call(1)[[2]]))[substitute(x)[[3]]])

(kết quả là như nhau).

Giải thích 2: sys.call(1)trả về lapply(...), vì vậy đó sys.call(1)[[2]]là biểu thức được sử dụng làm đối số danh sách lapply. Vượt qua điều này để evaltạo ra một đối tượng hợp pháp namescó thể truy cập. Lừa, nhưng nó hoạt động.

Phần thưởng: cách thứ hai để có được tên:

lapply(list(a=10,b=10,c=10), function(x)eval.parent(quote(names(X)))[substitute(x)[[3]]])

Lưu ý rằng đó Xlà một đối tượng hợp lệ trong khung chính của FUNvà tham chiếu đối số danh sách của lapply, vì vậy chúng ta có thể truy cập nó với eval.parent.


2
lapply(list(a=10,b=10,c=10), function(x)substitute(x)[[3]])đang trả về tất cả là 3. Bạn có thể giải thích cách 3 này được chọn không? và lý do cho sự khác biệt? Có bằng độ dài của danh sách không, trong trường hợp này là 3. Xin lỗi nếu đây là câu hỏi cơ bản nhưng muốn biết cách áp dụng điều này trong trường hợp chung.
Anusha

@Anusha, thực sự, hình thức đó không còn hoạt động nữa ... Nhưng lapply(list(a=10,b=10,c=10), function(x)eval.parent(quote(names(X)))[substitute(x)[[3]]])công việc ... Tôi sẽ kiểm tra xem chuyện gì đang xảy ra.
Ferdinand.kraft

@ Ferdinand.kraft, lapply(list(a=10,b=10,c=10), function(x)eval.parent(quote(names(X)))[substitute(x)[[3]]])không còn hoạt động và đưa ra lỗi, Error in eval.parent(quote(names(X)))[substitute(x)[[3]]] : invalid subscript type 'symbol'có cách nào dễ dàng để khắc phục điều này không?
dự báo

Cảm ơn bạn rất nhiều @ Ferdinand.kraft
forecaster

18

Tôi đã gặp vấn đề tương tự rất nhiều lần ... Tôi đã bắt đầu sử dụng một cách khác ... Thay vì sử dụng lapply, tôi đã bắt đầu sử dụngmapply

n = names(mylist)
mapply(function(list.elem, names) { }, list.elem = mylist, names = n)

2
Tôi cũng thích điều này, nhưng câu trả lời này là một bản sao của câu hỏi trước .
merv

13

Bạn có thể thử sử dụng imap()từ purrrgói.

Từ tài liệu:

imap (x, ...) là viết tắt của map2 (x, tên (x), ...) nếu x có tên hoặc map2 (x, seq_along (x), ...) nếu không.

Vì vậy, bạn có thể sử dụng nó theo cách đó:

library(purrr)
myList <- list(a=11,b=12,c=13) 
imap(myList, function(x, y) paste(x, y))

Sẽ cho bạn kết quả như sau:

$a
[1] "11 a"

$b
[1] "12 b"

$c
[1] "13 c"

10

Chỉ cần lặp trong tên.

sapply(names(mylist), function(n) { 
    doSomething(mylist[[n]])
    cat(n, '\n')
}

Đây chắc chắn là giải pháp đơn giản nhất.
bay

1
@fly: có, ngoại trừ thực tế xấu đối với biến mã cứng mylistbên trong hàm. Vẫn tốt hơn để làmfunction(mylist, nm) ...
smci

5

Câu trả lời của Tommy áp dụng cho các vectơ được đặt tên nhưng tôi có ý tưởng bạn quan tâm đến danh sách. Và có vẻ như anh ta đang kết thúc vì anh ta đang tham khảo "x" từ môi trường gọi. Hàm này chỉ sử dụng các tham số được truyền cho hàm và do đó không đưa ra giả định nào về tên của các đối tượng được truyền:

x <- list(a=11,b=12,c=13)
lapply(x, function(z) { attributes(deparse(substitute(z)))$names  } )
#--------
$a
NULL

$b
NULL

$c
NULL
#--------
 names( lapply(x, function(z) { attributes(deparse(substitute(z)))$names  } ))
#[1] "a" "b" "c"
 what_is_my_name <- function(ZZZ) return(deparse(substitute(ZZZ)))
 what_is_my_name(X)
#[1] "X"
what_is_my_name(ZZZ=this)
#[1] "this"
 exists("this")
#[1] FALSE

Chức năng của bạn chỉ trả về NULL?! Vì vậy, lapply(x, function(x) NULL)đưa ra câu trả lời tương tự ...
Tommy

Lưu ý rằng lapplyluôn luôn thêm tên từ xkết quả sau đó .
Tommy

Đúng. Đồng ý rằng đó là bài học của bài tập này.
IRTFM

4

Câu trả lời của tôi đi cùng hướng với Tommy và caracals, nhưng tránh phải lưu danh sách dưới dạng một đối tượng bổ sung.

lapply(seq(3), function(i, y=list(a=14,b=15,c=16)) { paste(names(y)[[i]], y[[i]]) })

Kết quả:

[[1]]
[1] "a 14"

[[2]]
[1] "b 15"

[[3]]
[1] "c 16"

Điều này đưa ra danh sách dưới dạng một đối số được đặt tên cho FUN (thay vào đó là lapply). lapply chỉ phải lặp đi lặp lại các yếu tố của danh sách (hãy cẩn thận thay đổi đối số đầu tiên này thành lapply khi thay đổi độ dài của danh sách).

Lưu ý: Đưa danh sách trực tiếp vào một cách khéo léo như một đối số bổ sung cũng hoạt động:

lapply(seq(3), function(i, y) { paste(names(y)[[i]], y[[i]]) }, y=list(a=14,b=15,c=16))

3

Cả @caracals và @Tommy đều là những giải pháp tốt và đây là một ví dụ bao gồm list´s và ọs data.frame.
rlà một listtrong listnhững người nổi tiếng và data.framengười khác ( dput(r[[1]]ở cuối).

names(r)
[1] "todos"  "random"
r[[1]][1]
$F0
$F0$rst1
   algo  rst  prec  rorac prPo pos
1  Mean 56.4 0.450 25.872 91.2 239
6  gbm1 41.8 0.438 22.595 77.4 239
4  GAM2 37.2 0.512 43.256 50.0 172
7  gbm2 36.8 0.422 18.039 85.4 239
11 ran2 35.0 0.442 23.810 61.5 239
2  nai1 29.8 0.544 52.281 33.1 172
5  GAM3 28.8 0.403 12.743 94.6 239
3  GAM1 21.8 0.405 13.374 68.2 239
10 ran1 19.4 0.406 13.566 59.8 239
9  svm2 14.0 0.385  7.692 76.2 239
8  svm1  0.8 0.359  0.471 71.1 239

$F0$rst5
   algo  rst  prec  rorac prPo pos
1  Mean 52.4 0.441 23.604 92.9 239
7  gbm2 46.4 0.440 23.200 83.7 239
6  gbm1 31.2 0.416 16.421 79.5 239
5  GAM3 28.8 0.403 12.743 94.6 239
4  GAM2 28.2 0.481 34.815 47.1 172
11 ran2 26.6 0.422 18.095 61.5 239
2  nai1 23.6 0.519 45.385 30.2 172
3  GAM1 20.6 0.398 11.381 75.7 239
9  svm2 14.4 0.386  8.182 73.6 239
10 ran1 14.0 0.390  9.091 64.4 239
8  svm1  6.2 0.370  3.584 72.4 239

Mục tiêu là unlisttất cả các danh sách, đặt chuỗi các listtên s làm cột để xác định trường hợp.

r=unlist(unlist(r,F),F)
names(r)
[1] "todos.F0.rst1"  "todos.F0.rst5"  "todos.T0.rst1"  "todos.T0.rst5"  "random.F0.rst1" "random.F0.rst5"
[7] "random.T0.rst1" "random.T0.rst5"

Bỏ danh sách nhưng không liệt kê data.frame.

ra=Reduce(rbind,Map(function(x,y) cbind(case=x,y),names(r),r))

Mapđặt chuỗi tên như một cột. Reducetham gia tất cả các vấn đề data.frame.

head(ra)
            case algo  rst  prec  rorac prPo pos
1  todos.F0.rst1 Mean 56.4 0.450 25.872 91.2 239
6  todos.F0.rst1 gbm1 41.8 0.438 22.595 77.4 239
4  todos.F0.rst1 GAM2 37.2 0.512 43.256 50.0 172
7  todos.F0.rst1 gbm2 36.8 0.422 18.039 85.4 239
11 todos.F0.rst1 ran2 35.0 0.442 23.810 61.5 239
2  todos.F0.rst1 nai1 29.8 0.544 52.281 33.1 172

PS r[[1]]:

    structure(list(F0 = structure(list(rst1 = structure(list(algo = c("Mean", 
    "gbm1", "GAM2", "gbm2", "ran2", "nai1", "GAM3", "GAM1", "ran1", 
    "svm2", "svm1"), rst = c(56.4, 41.8, 37.2, 36.8, 35, 29.8, 28.8, 
    21.8, 19.4, 14, 0.8), prec = c(0.45, 0.438, 0.512, 0.422, 0.442, 
    0.544, 0.403, 0.405, 0.406, 0.385, 0.359), rorac = c(25.872, 
    22.595, 43.256, 18.039, 23.81, 52.281, 12.743, 13.374, 13.566, 
    7.692, 0.471), prPo = c(91.2, 77.4, 50, 85.4, 61.5, 33.1, 94.6, 
    68.2, 59.8, 76.2, 71.1), pos = c(239L, 239L, 172L, 239L, 239L, 
    172L, 239L, 239L, 239L, 239L, 239L)), .Names = c("algo", "rst", 
    "prec", "rorac", "prPo", "pos"), row.names = c(1L, 6L, 4L, 7L, 
    11L, 2L, 5L, 3L, 10L, 9L, 8L), class = "data.frame"), rst5 = structure(list(
        algo = c("Mean", "gbm2", "gbm1", "GAM3", "GAM2", "ran2", 
        "nai1", "GAM1", "svm2", "ran1", "svm1"), rst = c(52.4, 46.4, 
        31.2, 28.8, 28.2, 26.6, 23.6, 20.6, 14.4, 14, 6.2), prec = c(0.441, 
        0.44, 0.416, 0.403, 0.481, 0.422, 0.519, 0.398, 0.386, 0.39, 
        0.37), rorac = c(23.604, 23.2, 16.421, 12.743, 34.815, 18.095, 
        45.385, 11.381, 8.182, 9.091, 3.584), prPo = c(92.9, 83.7, 
        79.5, 94.6, 47.1, 61.5, 30.2, 75.7, 73.6, 64.4, 72.4), pos = c(239L, 
        239L, 239L, 239L, 172L, 239L, 172L, 239L, 239L, 239L, 239L
        )), .Names = c("algo", "rst", "prec", "rorac", "prPo", "pos"
    ), row.names = c(1L, 7L, 6L, 5L, 4L, 11L, 2L, 3L, 9L, 10L, 8L
    ), class = "data.frame")), .Names = c("rst1", "rst5")), T0 = structure(list(
        rst1 = structure(list(algo = c("Mean", "ran1", "GAM1", "GAM2", 
        "gbm1", "svm1", "nai1", "gbm2", "svm2", "ran2"), rst = c(22.6, 
        19.4, 13.6, 10.2, 9.6, 8, 5.6, 3.4, -0.4, -0.6), prec = c(0.478, 
        0.452, 0.5, 0.421, 0.423, 0.833, 0.429, 0.373, 0.355, 0.356
        ), rorac = c(33.731, 26.575, 40, 17.895, 18.462, 133.333, 
        20, 4.533, -0.526, -0.368), prPo = c(34.4, 52.1, 24.3, 40.7, 
        37.1, 3.1, 14.4, 53.6, 54.3, 116.4), pos = c(195L, 140L, 
        140L, 140L, 140L, 195L, 195L, 140L, 140L, 140L)), .Names = c("algo", 
        "rst", "prec", "rorac", "prPo", "pos"), row.names = c(1L, 
        9L, 3L, 4L, 5L, 7L, 2L, 6L, 8L, 10L), class = "data.frame"), 
        rst5 = structure(list(algo = c("gbm1", "ran1", "Mean", "GAM1", 
        "GAM2", "svm1", "nai1", "svm2", "gbm2", "ran2"), rst = c(17.6, 
        16.4, 15, 12.8, 9, 6.2, 5.8, -2.6, -3, -9.2), prec = c(0.466, 
        0.434, 0.435, 0.5, 0.41, 0.8, 0.44, 0.346, 0.345, 0.337), 
            rorac = c(30.345, 21.579, 21.739, 40, 14.754, 124, 23.2, 
            -3.21, -3.448, -5.542), prPo = c(41.4, 54.3, 35.4, 22.9, 
            43.6, 2.6, 12.8, 57.9, 62.1, 118.6), pos = c(140L, 140L, 
            195L, 140L, 140L, 195L, 195L, 140L, 140L, 140L)), .Names = c("algo", 
        "rst", "prec", "rorac", "prPo", "pos"), row.names = c(5L, 
        9L, 1L, 3L, 4L, 7L, 2L, 8L, 6L, 10L), class = "data.frame")), .Names = c("rst1", 
    "rst5"))), .Names = c("F0", "T0"))

0

Hãy nói rằng chúng tôi muốn tính toán độ dài của từng yếu tố.

mylist <- list(a=1:4,b=2:9,c=10:20)
mylist

$a
[1] 1 2 3 4

$b
[1] 2 3 4 5 6 7 8 9

$c
 [1] 10 11 12 13 14 15 16 17 18 19 20

Nếu mục đích là chỉ dán nhãn các yếu tố kết quả, thì lapply(mylist,length)hoặc bên dưới hoạt động.

sapply(mylist,length,USE.NAMES=T)

 a  b  c 
 4  8 11 

Nếu mục đích là sử dụng nhãn bên trong hàm, thì mapply()hữu ích bằng cách lặp qua hai đối tượng; các yếu tố danh sách và tên danh sách.

fun <- function(x,y) paste0(length(x),"_",y)
mapply(fun,mylist,names(mylist))

     a      b      c 
 "4_a"  "8_b" "11_c" 

0

@ ferdinand-kraft đã cho chúng tôi một mẹo hay và sau đó nói với chúng tôi rằng chúng tôi không nên sử dụng nó vì nó không có giấy tờ và vì hiệu suất quá cao.

Tôi không thể tranh luận nhiều với điểm đầu tiên nhưng tôi muốn lưu ý rằng chi phí này hiếm khi là một mối quan tâm.

hãy xác định các hàm hoạt động để chúng ta không phải gọi biểu thức phức tạp parent.frame()$i[]mà chỉ .i(), Chúng ta cũng sẽ tạo .n()để truy cập tên, hoạt động cho cả hai hàm cơ sởpurrr (và có lẽ là hầu hết các hàm khác).

.i <- function() parent.frame(2)$i[]
# looks for X OR .x to handle base and purrr functionals
.n <- function() {
  env <- parent.frame(2)
  names(c(env$X,env$.x))[env$i[]]
}

sapply(cars, function(x) paste(.n(), .i()))
#>     speed      dist 
#> "speed 1"  "dist 2"

Bây giờ, hãy điểm chuẩn một hàm đơn giản sẽ dán các mục của vectơ vào chỉ mục của chúng, sử dụng các cách tiếp cận khác nhau (hoạt động này tất nhiên có thể được vector hóa bằng cách sử dụng paste(vec, seq_along(vec))nhưng đó không phải là điểm ở đây).

Chúng tôi xác định chức năng đo điểm chuẩn và chức năng vẽ đồ thị và vẽ kết quả dưới đây:

library(purrr)
library(ggplot2)
benchmark_fun <- function(n){
  vec <- sample(letters,n, replace = TRUE)
  mb <- microbenchmark::microbenchmark(unit="ms",
                                      lapply(vec, function(x)  paste(x, .i())),
                                      map(vec, function(x) paste(x, .i())),
                                      lapply(seq_along(vec), function(x)  paste(vec[[x]], x)),
                                      mapply(function(x,y) paste(x, y), vec, seq_along(vec), SIMPLIFY = FALSE),
                                      imap(vec, function(x,y)  paste(x, y)))
  cbind(summary(mb)[c("expr","mean")], n = n)
}

benchmark_plot <- function(data, title){
  ggplot(data, aes(n, mean, col = expr)) + 
    geom_line() +
    ylab("mean time in ms") +
    ggtitle(title) +
    theme(legend.position = "bottom",legend.direction = "vertical")
}

plot_data <- map_dfr(2^(0:15), benchmark_fun)
benchmark_plot(plot_data[plot_data$n <= 100,], "simplest call for low n")

benchmark_plot(plot_data,"simplest call for higher n")

Được tạo vào ngày 2019-11-15 bởi gói reprex (v0.3.0)

Sự sụt giảm ở đầu biểu đồ đầu tiên là một con sán, xin vui lòng bỏ qua nó.

Chúng tôi thấy rằng câu trả lời được chọn thực sự nhanh hơn và với số lần lặp vừa phải, các .i()giải pháp của chúng tôi thực sự chậm hơn, chi phí so với câu trả lời được chọn là khoảng 3 lần chi phí sử dụng purrr::imap()và khoảng 25 ms cho 30 lần lặp, vì vậy tôi mất khoảng 1 ms trên 1000 lần lặp, 1 giây trên một triệu. Đó là một chi phí nhỏ cho sự thuận tiện theo ý kiến ​​của tôi.


-1

Chỉ cần viết lapplychức năng tùy chỉnh của riêng bạn

lapply2 <- function(X, FUN){
  if( length(formals(FUN)) == 1 ){
    # No index passed - use normal lapply
    R = lapply(X, FUN)
  }else{
    # Index passed
    R = lapply(seq_along(X), FUN=function(i){
      FUN(X[[i]], i)
    })
  }

  # Set names
  names(R) = names(X)
  return(R)
}

Sau đó sử dụng như thế này:

lapply2(letters, function(x, i) paste(x, i))

điều này không mạnh chút nào, hãy thận trọng
Moody_Mudskipper
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.