R 中的压缩或枚举?

发布于 2025-01-06 02:50:41 字数 645 浏览 0 评论 0原文

这些Python列表推导式的R等价物是什么:

[(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

输出示例

>>> [(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)]

我之前用R中的一些技巧解决了这个问题,但不再记得了,第一个想法是itertools -pkg,但我希望找到一种更惯用的做事方式。

What are the R equivalents for these Python list comprehensions:

[(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

Example with Output

>>> [(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)]

I have solved this problem earlier with some trick in R but cannot remember anymore, the first idea was itertools -pkg but I am hoping to find a more idiomatic way of doing things.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

千笙结 2025-01-13 02:50:41

python enumerate 的答案:

在 R 中,列表是有序的(请参阅 这个答案)。因此,您所需要做的就是为键(使用 names()[i])或值(使用 [[i]])建立索引。

使用 seq_along (或者可以做 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"

python zip 的答案:

请参阅上述答案之一来模拟元组列表。我更喜欢 BondedDust 的答案中所示的数据框:

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

Answer for python enumerate:

In R, a list is ordered (see this answer). Thus, all you need is to index either keys (using names()[i]) or values (using [[i]]).

Using seq_along (alternatively can do 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"

Answer for python zip:

See one of the above answers to mimic the list of tuples. My preference is towards a data frame as shown in BondedDust's answer:

> x <- 1:3
> y <- 4:6
> data.frame(x=x, y=y)
  x y
1 1 4
2 2 5
3 3 6
灼疼热情 2025-01-13 02:50:41

关于 R 的列表理解有一些讨论,例如 此处那里hash 包甚至提供类似字典的结构。然而,正如其他人所说,很难尝试将一种语言设施映射到另一种语言设施上(即使这是比较编程语言实际上提供了),但不清楚它应该用来做什么。例如,我可以在 R 中模仿 Python zip(),如下所示:

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 

可以看出,这实际上取决于您想要什么与事后的结果有关。

There have been some discussions around list comprehension for R, e.g. here or there. The hash package even offers dictionary-like structure. However, as others said, it is difficult to try to map one language facilities onto another (even if this is what Comparison of programming languages actually offers) without a clear understanding of what it is supposed to be used to. For example, I can mimic Python zip() in R as follows:

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 

As can be seen, this really depends on what you want to do with the result afterwards.

℡寂寞咖啡 2025-01-13 02:50:41

zipenumerate 在 R 中实现起来并不是特别困难:

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

枚举很容易用 zip 来定义:

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

由于这些是正确的函数,我们可以使用 ... 使它们相当灵活和简洁,并利用 mapply 的行为,例如回收输入和正确命名输出。

zip and enumerate are not particularly difficult to implement in R:

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

Enumerate is simple to define in terms of zip:

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

Since these are proper functions, we can use ... to make them fairly flexible and terse, and take advantage of mapply's behavior, such as recycling inputs and naming output correctly.

黑凤梨 2025-01-13 02:50:41

创建向量列表的另一个选项是使用 Map 函数,如 @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

Another option which will create a list of vectors is to use the Map function as seen here by @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
极度宠爱 2025-01-13 02:50:41

如果这是矩阵的 Python 打印表示,那么这段代码:

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

对于我们这些非 Python 用户来说,您仍然对所需输出的结构一无所知。您使用术语“列表”,但输出表明一组有序的元组。

根据 @chi 的指导,我们可能还建议使用以 R 为中心的“数据框架”结构

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

……它在列类型方面具有列表的灵活性,在行和列索引方面具有矩阵的访问功能。或者,可以使用 hhh 的请求并使用默认从“1”开始的 rownames 向量创建 j 向量的隐式索引值 10:20,但是它可以被更改为从“0”开始的字符向量

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

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

不幸的是,粗心的人会发现 dfrm[0, ] 不是一个愉快的调用,返回长度为 0 的向量。

If that is the Python print representation of a matrix, then this code:

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

You are still leaving those of us who are not Python users in the dark regarding the structure of your desired output. You use the term "list" but the output suggests an ordered set of tuples.

Given @chi's guidance we might also suggest using the very R-centric 'dataframe' structure

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

... which has the flexibility of a list in terms of column types and the access features of a matrix in terms of row and column indexing. Or one could use hhh's request and create the implicitly indexed values of the j-vector, 10:20, using the rownames vector that starts at "1" by default, but which could be altered to become a character vector starting at "0"

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

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

Unfortunately, the unwary will find that dfrm[0, ] is not a happy call, returning vector of length 0.

壹場煙雨 2025-01-13 02:50:41

为了将 Python 风格的列表推导式与枚举(例如枚举列表)一起使用,一种方法是安装列表推导式包 LC(2018 年开发)和 itertools 包(2015 年开发)。

R 中的列表推导式

您可以在此处<找到LC 包< /a>.

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

示例

> 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"

,其中编程语法尚未像 Python 那样干净和完善,但功能正常,其帮助概述:

“语法如下:lc(expr,lists,predicates),其中expr是要对列表中的所有元素求值的某个表达式,其中
列表是一个或多个命名列表,其中这些列表由名称指定
和表达式 name = list_expr,其中谓词是
应计算为布尔值的表达式。例如,要
从我们可以写的列表 x 中获取所有偶数的平方列表
lc(x ** 2, x = x, x %% 2 == 0)。调用 lc 的结果是一个列表
对于 expr 中的所有元素,根据 expr 中的表达式构造
输入列表,其中谓词评估为 true。”

其中请注意,您可以将谓词保留为空,例如在上面的示例中。

Python 风格的 itertools 和枚举

您可以使用 R 的 itertools,它与 Python 的 itertools 非常相似itertools,进一步在 Cran 此处

library(itertools)

描述的地方

“用于创建迭代器的各种工具,Python itertools 模块中的许多仿照函数,以及其他仿照函数的工具
在“雪”包中。”

示例.枚举

> 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"

示例.带 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"

In order to use Python style list comprehensions with enumerations, such as enumerated lists, one way is to install List-comprehension package LC (developed 2018) and itertools package (developed 2015).

List comprehensions in R

You can find the LC package here.

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

Example

> 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"

where the programming syntax is not yet as clean and polished as in Python but functionally working and its help outlines:

"The syntax is as follows: lc(expr, lists, predicates) where expr is some expression to be evaluated for all elements in the lists, where
lists are one or more named lists, where these are specified by a name
and an expression name = list_expr, and where predicates are
expressions that should evaluated to a boolean value. For example, to
get a list of all even numbers, squared, from a list x we can write
lc(x ** 2, x = x, x %% 2 == 0). The result of a call to lc is a list
constructed from the expressions in expr, for all elements in the
input lists where the predicates evaluate to true."

where notice that you can leave the predicates empty for example in the above example.

Python-style itertools and enumerations

You can use R's itertools that is very similar to Python's itertools, further in Cran here

library(itertools)

where described

"Various tools for creating iterators, many patterned after functions in the Python itertools module, and others patterned after functions
in the 'snow' package."

Example. enumeration

> 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"

Example. enumeration with 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"
陌路终见情 2025-01-13 02:50:41

这可以使用两个粘贴语句来实现:

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

输出如下:

'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'

This can be achieved using two paste statements:

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

Output will like following:

'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'
っ〆星空下的拥抱 2025-01-13 02:50:41

对于 python,R 中的“枚举”等效项。将向量存储在列表中并使用索引迭代它们应该可以正常工作。

vect1 <- c('A', 'B', 'C')
vect2 <- c('a', 'b', 'c')

# eqiv to zip values:
idx_list <- list(vect1, vect2)
idx_vect <- c(1:length(idx_list[[1]]))

for(i in idx_vect){
    x <- idx_list[[1]][i]
    j <- idx_list[[2]][i]
    print(c(i, x, j))
}

输出:

[1] "1" "A" "a"
[1] "2" "B" "b"
[1] "3" "C" "c"

R“列表”是一个很好的存储库,用于存储向量并保留索引。

For python, 'enumerate' equivalent in R. Storing the vectors in the list and iterating over them with an index should work fine.

vect1 <- c('A', 'B', 'C')
vect2 <- c('a', 'b', 'c')

# eqiv to zip values:
idx_list <- list(vect1, vect2)
idx_vect <- c(1:length(idx_list[[1]]))

for(i in idx_vect){
    x <- idx_list[[1]][i]
    j <- idx_list[[2]][i]
    print(c(i, x, j))
}

Output:

[1] "1" "A" "a"
[1] "2" "B" "b"
[1] "3" "C" "c"

R 'list' is a nice bank for depositing the vectors and retain with an index.

罗罗贝儿 2025-01-13 02:50:41
# 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
    })
}
# 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
    })
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文