¿Cuáles son los equivalentes de R para estas comprensiones de listas de Python?
[(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
Ejemplo con salida
>>> [(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)]
Resolví este problema anteriormente con algún truco en R pero ya no puedo recordar, la primera idea fue itertools -pkg pero espero encontrar una forma más idiomática de hacer las cosas.
expand.grid(i=10:20,j=10:20)
as.vector(rbind(1:10, 11:20))
Respuestas:
Respuesta para Python
enumerate
:En R, se ordena una lista (consulte esta respuesta ). Por lo tanto, todo lo que necesita es indexar claves (usando
names()[i]
) o valores (usando[[i]]
).Usando
seq_along
(alternativamente puede hacerfor(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"
Respuesta para Python
zip
:Vea una de las respuestas anteriores para imitar la lista de tuplas. Mi preferencia es hacia un marco de datos como se muestra en la respuesta de BondedDust:
> x <- 1:3 > y <- 4:6 > data.frame(x=x, y=y) x y 1 1 4 2 2 5 3 3 6
fuente
data.frame(names=labels(mylist),values=unlist(mylist),row.names = 1:length(mylist))
Ha habido algunas discusiones sobre la comprensión de listas para R, por ejemplo, aquí o allá . El paquete hash incluso ofrece una estructura similar a la de un diccionario. Sin embargo, como dijeron otros, es difícil intentar mapear las instalaciones de un lenguaje con otro (incluso si esto es lo que realmente ofrece la comparación de lenguajes de programación ) sin una comprensión clara de a qué se supone que está acostumbrado. Por ejemplo, puedo imitar Python
zip()
en R de la siguiente manera:Pitón
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
Como se puede ver, esto realmente depende de lo que quieras hacer con el resultado después.
fuente
mapply
es lo que queremos para el análogo directa.mapply
cubre el caso de uso más común: zip, luego map.Otra opción que creará una lista de vectores es usar la función Mapa como la ve aquí @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
fuente
for xi, yi in zip(x, y): ...
. +1 para la solución más elegante que he visto hasta ahora para hacer esto en R:for (xi.yi in Map(c, x, y)) { xi <- xi.yi[1]; yi <- xi.yi[2]; ... }
Si esa es la representación impresa de Python de una matriz, entonces este código:
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
Todavía nos está dejando a aquellos de nosotros que no somos usuarios de Python en la oscuridad con respecto a la estructura de su salida deseada. Utiliza el término "lista" pero el resultado sugiere un conjunto ordenado de tuplas.
Dada la orientación de @ chi, también podríamos sugerir el uso de la estructura de 'marco de datos' muy centrada en R
x <- 1:3 y <- 4:6 dfrm <- data.frame(x=x, y=y)
... que tiene la flexibilidad de una lista en términos de tipos de columnas y las características de acceso de una matriz en términos de indexación de filas y columnas. O uno podría usar la solicitud de hhh y crear los valores indexados implícitamente del vector j
10:20
, usando elrownames
vector que comienza en "1" por defecto, pero que podría modificarse para convertirse en un vector de caracteres que comienza en "0"dfrm <- data.frame(j=10:20) dfrm[3, ] #[1] 12 rownames(dfrm) <- 0:10 dfrm["0",] # [1] 10
Desafortunadamente, los incautos encontrarán que dfrm [0,] no es una llamada feliz, devolviendo un vector de longitud 0.
fuente
Para utilizar listas por comprensión de estilo Python con enumeraciones, como listas enumeradas, una forma es instalar el paquete List-comprehension
LC
(desarrollado en 2018) y el paquete itertools (desarrollado en 2015).Lista de comprensiones en R
Puedes encontrar el
LC
paquete aquí .install.packages("devtools") devtools::install_github("mailund/lc")
Ejemplo
> 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"
donde la sintaxis de programación aún no es tan limpia y pulida como en Python, pero funciona funcionalmente y sus esquemas de ayuda:
donde observe que puede dejar los predicados vacíos, por ejemplo, en el ejemplo anterior.
Itertools y enumeraciones de estilo Python
Puede usar las herramientas de iteración de R que son muy similares a las herramientas de iteración de Python, más adelante en Cran aquí
library(itertools)
donde se describe
Ejemplo. enumeración
> 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"
Ejemplo. enumeración con 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"
fuente
zip
yenumerate
no son particularmente difíciles de implementar en R:#' zip(1:5,1:10) zip <- function(...) { mapply(list, ..., SIMPLIFY = FALSE) }
Enumerar es simple de definir en términos de
zip
:#' enumerate(l=LETTERS) enumerate <- function(...) { zip(ix=seq_along(..1), ...) }
Dado que estas son funciones adecuadas, podemos utilizarlas
...
para hacerlas bastante flexibles y concisas, y aprovechar el comportamiento de mapply, como reciclar entradas y nombrar las salidas correctamente.fuente
stackoverflow
paquete, fwiw.# 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 }) }
fuente
Esto se puede lograr usando dos declaraciones de pegado:
str1 <- paste(1:11, 10:20, sep=",", collapse='), (') paste("(", str1, ")", sep = "")
A la salida le gustará lo siguiente:
'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'
fuente