邮编或枚举R?


82

这些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,但是我希望找到一种更惯用的做事方式。


2
如果您可以为不熟悉Python的人提供一个小型的可行示例,则可能会增加潜在答题者的数量。我猜最后一个是expand.grid(i=10:20,j=10:20)
Ben Bolker

@BenBolker:添加了输出-现在清除了吗?可能更具挑战性,但逻辑很重要……
2012年

1
我同意@DWin。期望R和Python中的数据结构之间存在一对一的映射是不合理的。如果想要好的答案,则应指定希望结果在R中而不是在Python中的外观。
joran 2012年

顺便说一下,这是压缩和展平两个列表的一种巧妙方法:as.vector(rbind(1:10, 11:20))
smci 2015年

Answers:


43

回答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

要将您的第一个示例延续到第二个示例中,data.frame(names=labels(mylist),values=unlist(mylist),row.names = 1:length(mylist))
Josiah Yoder

42

围绕R的列表理解已经进行了一些讨论,例如herethere。该包甚至提供类似字典的结构。但是,就像其他人所说的那样,如果不明确了解应该习惯使用哪种语言,就很难尝试将一种语言设施映射到另一种语言设施(即使这是“编程语言比较”实际上提供的)。例如,我可以模仿zip()R中的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 

可以看出,这实际上取决于您随后要对结果做什么。


1
我认为问题是,当您在python中使用zip时会使用什么。典型的用法是使用多个参数进行列表理解,因此mapply直接处理它。
seanv507

6
mapply就是我们想要直接模拟的东西。
StephenBoesch

@javadbamapply涵盖了最常见的用例:zip,然后是map。
约西亚·约德

7

另一个将创建向量列表的选项是使用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

在Python中,zip的主要用途是在多个向量/列表上进行迭代:for xi, yi in zip(x, y): ...。+1是迄今为止我在R中看到的最优雅的解决方案:for (xi.yi in Map(c, x, y)) { xi <- xi.yi[1]; yi <- xi.yi[2]; ... }
sgrubsmyon

6

如果那是矩阵的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的请求并10:20使用rownames默认情况下以“ 1”开始的矢量创建j-vector的隐式索引值,但也可以将其更改为以“ 0”开始的字符矢量

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

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

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


+1是一种优雅的解决方案。(不,这些不是Python矩阵,但您已经猜到了它的元组列表。)
chl 2012年

4

为了对枚举(例如枚举列表)使用Python样式列表推导,一种方法是安装List-comprehension包LC(于2018年开发)和itertools包(于2015年开发)。

R中的列表理解

您可以在这里找到LC软件包。

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,列表,谓词)其中expr是要对列表中的所有元素求值的某种表达式,其中列表是一个或多个命名列表,其中用名称和表达式名称指定= list_expr,其中谓词是应评估为布尔值的表达式,例如,要从列表x中获取所有偶数平方的列表,我们可以编写lc(x ** 2,x = x,x% %2 == 0)。lc的调用结果是一个由expr中的表达式构成的列表,用于谓词为true的输入列表中的所有元素。”

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

Python样式的itertools和枚举

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

library(itertools)

描述的地方

“用于创建迭代器的各种工具,其中许多在Python itertools模块中以函数为后继,而在'snow'包中以函数为后继。

例。枚举

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

3

zip并且enumerate在R中实施起来并不是特别困难:

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

枚举的定义很简单zip

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

由于这些功能是适当的,因此我们可以使用...它们来使它们变得相当灵活和简洁,并利用mapply的行为,例如正确回收输入和正确命名输出。


1
这些已添加到stackoverflow程序包中。
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
    })
}

请提供有关此代码块的功能的描述。
Keivan Esbati

此功能与@chl指出的“ mapply(list,x,y,SIMPLIFY = F)”功能完全相同
ibilgen

0

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

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)'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.