Zip hoặc liệt kê trong R?


82

Tương đương R là gì cho các cách hiểu danh sách Python này:

[(i,j) for i,j in zip(index, Values)]
[(i,j) for i,j in enumerate(Values)]
[(i,j) for i,j in enumerate(range(10,20))]   %MWE, indexing or enumerating to 
                                            %keep up with the index, there may 
                                            %be some parameter to look this up

Ví dụ với Đầu ra

>>> [(i,j) for i,j in enumerate(range(10,20))]
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]

Tôi đã giải quyết vấn đề này trước đó với một số mẹo trong R nhưng không thể nhớ được nữa, ý tưởng đầu tiên là itertools -pkg nhưng tôi hy vọng sẽ tìm ra một cách làm thành ngữ hơn.


2
nếu bạn có thể đưa ra một ví dụ nhỏ hữu ích cho những người trong chúng ta không quen thuộc với Python, nó có thể tăng dân số người trả lời tiềm năng. Tôi đoán rằng người cuối cùng làexpand.grid(i=10:20,j=10:20)
Ben Bolker 14/02/12

@BenBolker: đã thêm một đầu ra - bây giờ rõ ràng? Nó có thể khó khăn hơn nhưng logic là quan trọng ...
hhh

1
Tôi đồng ý với @DWin. Thật không hợp lý khi mong đợi một ánh xạ 1-1 giữa các cấu trúc dữ liệu trong R và Python. Nếu bạn muốn có câu trả lời tốt, bạn nên chỉ định cách bạn muốn kết quả trông như thế nào trong R chứ không phải trong Python.
joran 14/02/12

Bằng cách này, đây là một cách gọn gàng để zip và san bằng hai danh sách:as.vector(rbind(1:10, 11:20))
SMCI

Câu trả lời:


43

Câu trả lời cho python enumerate:

Trong R, một danh sách được sắp xếp (xem câu trả lời này ). Vì vậy, tất cả những gì bạn cần là lập chỉ mục các khóa (sử dụng names()[i]) hoặc các giá trị (sử dụng [[i]]).

Sử dụng seq_along(cách khác có thể làm for(i in 1:length(mylist)){...}):

> mylist <- list('a'=10,'b'=20,'c'=30)
> for (i in seq_along(mylist)){
+   print(paste(i,names(mylist)[i],mylist[[i]]))
+ }
[1] "1 a 10"
[1] "2 b 20"
[1] "3 c 30"

Câu trả lời cho python zip:

Xem một trong các câu trả lời ở trên để bắt chước danh sách các bộ giá trị. Sở thích của tôi là hướng tới khung dữ liệu như trong câu trả lời của BondedDust:

> x <- 1:3
> y <- 4:6
> data.frame(x=x, y=y)
  x y
1 1 4
2 2 5
3 3 6

Để tiếp tục ví dụ đầu tiên của bạn sang ví dụ thứ hai,data.frame(names=labels(mylist),values=unlist(mylist),row.names = 1:length(mylist))
Josiah Yoder,

42

Đã có một số cuộc thảo luận xung quanh việc hiểu danh sách cho R, ví dụ như ở đây hoặc ở đó . Các băm gói thậm chí cung cấp từ điển giống như cấu trúc. Tuy nhiên, như những người khác đã nói, rất khó để cố gắng ánh xạ một cơ sở ngôn ngữ này sang một ngôn ngữ khác (ngay cả khi đây là những gì So sánh các ngôn ngữ lập trình thực sự cung cấp) mà không hiểu rõ ràng về những gì nó được cho là được sử dụng. Ví dụ: tôi có thể bắt chước Python zip()trong R như sau:

Python

In [1]: x = [1,2,3]
In [2]: y = [4,5,6]
In [3]: zip(x, y)
Out[3]: [(1, 4), (2, 5), (3, 6)]

R

> x <- 1:3
> y <- 4:6
> list(x, y)                     # gives a simple list
> as.list(paste(x, y))           # three tuples, as a list of characters
> mapply(list, x, y, SIMPLIFY=F) # gives a list of 3 tuples
> rbind(x, y)                    # gives a 2x3 matrix 

Có thể thấy, điều này thực sự phụ thuộc vào những gì bạn muốn làm với kết quả sau đó.


1
Tôi nghĩ câu hỏi là bạn sẽ sử dụng gì khi sử dụng zip trong python. cách sử dụng điển hình là để hiểu danh sách với nhiều đối số để mapply xử lý điều này trực tiếp.
seanv507

6
Đây mapplylà những gì chúng tôi muốn cho tương tự trực tiếp.
StephenBoesch

@javadba mapplybao gồm trường hợp sử dụng phổ biến nhất: zip, sau đó là bản đồ.
Josiah Yoder

7

Một tùy chọn khác sẽ tạo danh sách các vectơ là sử dụng chức năng Bản đồ như được thấy ở đây bởi @peterhurford: https://rdrr.io/github/peterhurford/funtools/src/R/zippers.R

> x <- 1:3
> y <- 4:6
> z <- 7:9
> Map(c, x, y, z)
[[1]]
[1] 1 4 7

[[2]]
[1] 2 5 8

[[3]]
[1] 3 6 9

Trong Python, việc sử dụng chính của zip là lặp đi lặp lại trên một số vectơ / danh sách: for xi, yi in zip(x, y): .... 1 cho các giải pháp thanh lịch nhất mà tôi đã nhìn thấy cho đến nay để làm điều này trong R:for (xi.yi in Map(c, x, y)) { xi <- xi.yi[1]; yi <- xi.yi[2]; ... }
sgrubsmyon

6

Nếu đó là biểu diễn in Python của một ma trận, thì mã này:

j <- 10:20
matrix(c(seq_along(j), j), ncol=2)
#------------
      [,1] [,2]
 [1,]    1   10
 [2,]    2   11
 [3,]    3   12
 [4,]    4   13
 [5,]    5   14
 [6,]    6   15
 [7,]    7   16
 [8,]    8   17
 [9,]    9   18
[10,]   10   19
[11,]   11   20

Bạn vẫn đang để những người trong chúng ta không phải là người dùng Python trong bóng tối về cấu trúc đầu ra mong muốn của bạn. Bạn sử dụng thuật ngữ "danh sách" nhưng đầu ra đề xuất một tập hợp các bộ giá trị có thứ tự.

Với hướng dẫn của @ chi, chúng tôi cũng có thể đề xuất sử dụng cấu trúc 'khung dữ liệu' trọng tâm R

x <- 1:3
y <- 4:6
dfrm <- data.frame(x=x, y=y)

... có tính linh hoạt của danh sách về loại cột và các tính năng truy cập của ma trận về lập chỉ mục hàng và cột. Hoặc người ta có thể sử dụng yêu cầu của hhh và tạo các giá trị được lập chỉ mục ngầm của vectơ j 10:20, sử dụng rownamesvectơ bắt đầu từ "1" theo mặc định, nhưng có thể được thay đổi để trở thành vectơ ký tự bắt đầu từ "0"

dfrm <- data.frame(j=10:20)
dfrm[3, ]
#[1] 12

 rownames(dfrm) <- 0:10
 dfrm["0",]
# [1] 10

Thật không may, người không cẩn thận sẽ thấy rằng dfrm [0,] không phải là một lệnh gọi vui, trả về vectơ có độ dài 0.


+1 cho một giải pháp thanh lịch. (Không, đó không phải là ma trận Python nhưng như bạn đã đoán nó là danh sách các bộ giá trị .)
chl 14/02/12

4

Để sử dụng tính năng hiểu danh sách kiểu Python với các kiểu liệt kê, chẳng hạn như danh sách được liệt kê, một cách là cài đặt gói Danh sách hiểu LC(phát triển 2018) và gói itertools (phát triển 2015).

Liệt kê các hiểu biết trong R

Bạn có thể tìm thấy LCgói ở đây .

install.packages("devtools")
devtools::install_github("mailund/lc")

Thí dụ

> library(itertools); library(lc)
> lc(paste(x$index, x$value), x=as.list(enumerate(rnorm(5))), )
[[1]]
[1] "1 -0.715651978438808"

[[2]]
[1] "2 -1.35430822605807"

[[3]]
[1] "3 -0.162872340884235"

[[4]]
[1] "4 1.42909760816254"

[[5]]
[1] "5 -0.880755983937781"

trong đó cú pháp lập trình chưa rõ ràng và bóng bẩy như trong Python nhưng hoạt động về mặt chức năng và trợ giúp của nó nêu rõ:

"Cú pháp như sau: lc (expr, danh sách, vị từ) trong đó expr là một số biểu thức được đánh giá cho tất cả các phần tử trong danh sách, trong đó danh sách là một hoặc nhiều danh sách được đặt tên, trong đó chúng được chỉ định bằng tên và tên biểu thức = list_expr và trong đó các vị từ là các biểu thức sẽ được đánh giá thành giá trị boolean. Ví dụ: để lấy danh sách tất cả các số chẵn, bình phương, từ danh sách x, chúng ta có thể viết lc (x ** 2, x = x, x% % 2 == 0). Kết quả của lệnh gọi tới lc là một danh sách được xây dựng từ các biểu thức trong expr, cho tất cả các phần tử trong danh sách đầu vào trong đó các vị từ đánh giá là true. "

nơi lưu ý rằng bạn có thể để trống các vị từ, ví dụ trong ví dụ trên.

Bảng kê và bảng kê kiểu Python

Bạn có thể sử dụng itertools của R rất giống với itertools của Python, thêm trong Cran tại đây

library(itertools)

nơi được mô tả

"Các công cụ khác nhau để tạo trình vòng lặp, nhiều công cụ được tạo mẫu sau các hàm trong mô-đun itertools Python và những công cụ khác được tạo mẫu sau các hàm trong gói 'snow'."

Thí dụ. sự liệt kê

> for (a in as.list(enumerate(rnorm(5)))) { print(paste(a$index, "index:", a$value))}
[1] "1 index: 1.63314811372568"
[1] "2 index: -0.983865948988314"
[1] "3 index: -1.27096072277818"
[1] "4 index: 0.313193212706331"
[1] "5 index: 1.25226639725357"

Thí dụ. liệt kê với ZIP

> for (h in as.list(izip(a=1:5, b=letters[1:5]))) { print(paste(h$a, "index:", h$b))}
[1] "1 index: a"
[1] "2 index: b"
[1] "3 index: c"
[1] "4 index: d"
[1] "5 index: e"

3

zipenumeratekhông đặc biệt khó triển khai trong R:

#' zip(1:5,1:10)
zip <- function(...) {
  mapply(list, ..., SIMPLIFY = FALSE)
}

Enumerate rất đơn giản để định nghĩa về zip:

#' enumerate(l=LETTERS)
enumerate <- function(...) {
  zip(ix=seq_along(..1), ...)
}

Vì đây là các chức năng thích hợp, chúng ta có thể sử dụng ...để làm cho chúng khá linh hoạt và ngắn gọn, đồng thời tận dụng hành vi của mapply, chẳng hạn như tái chế đầu vào và đặt tên đầu ra một cách chính xác.


1
Chúng đã được thêm vào stackoverflowgói, fwiw.
Neal Fultz

0
# similar to python. return a list of list. Short sequences get recycled.
zip <- function(...){ 
    all.list <- list(...)
    ele.names <- names(all.list)
    max.length <- max(sapply(all.list, length))
    lapply(0:(max.length - 1), function(i) {
        res <- lapply(all.list, function(l) l[i %% length(l) + 1]) 
        names(res) <- ele.names
        res
    })
}

Vui lòng cung cấp mô tả về chức năng của khối mã này.
Keivan Esbati,

hàm này thực hiện chính xác điều tương tự với "mapply (list, x, y, SIMPLIFY = F)" mà @chl đã trỏ
ibilgen

0

Điều này có thể đạt được bằng cách sử dụng hai câu lệnh dán:

str1 <- paste(1:11, 10:20, sep=",", collapse='), (')
paste("(", str1, ")", sep = "")

Đầu ra sẽ như sau:

'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'
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.