web-dev-qa-db-fra.com

Zip ou énumérer dans R?

Quels sont les équivalents R de ces compréhensions de liste 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

Exemple avec sortie

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

J'ai résolu ce problème plus tôt avec un truc en R mais je ne m'en souviens plus, la première idée était itertools -pkg mais j'espère trouver une façon plus idiomatique de faire les choses. 

52
hhh

Il y a eu des discussions sur la compréhension de liste pour R, par exemple. ici ou . Le package hash offre même une structure de type dictionnaire. Cependant, comme d’autres l’ont dit, il est difficile d’essayer de mapper une installation linguistique sur une autre (même si c’est ce que Comparaison des langages de programmation offre réellement) sans une compréhension claire de ce à quoi elle est censée être utilisée. Par exemple, je peux imiter Python Zip() dans R comme suit:

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 

Comme on peut le constater, cela dépend vraiment de ce que vous voulez faire avec le résultat.

33
chl

Réponse pour python enumerate:

Dans R, une liste est ordonnée (voir cette réponse ). Ainsi, tout ce dont vous avez besoin est d’indexer les clés (avec names()[i]) ou les valeurs (avec [[i]]).

En utilisant seq_along (peut alternativement faire 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"

Réponse pour python Zip:

Voir l'une des réponses ci-dessus pour imiter la liste des n-uplets. Ma préférence va vers un bloc de données, comme indiqué dans la réponse 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
29
Theja

S'il s'agit de la représentation d'impression Python d'une matrice, alors ce 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

Vous laissez encore ceux d'entre nous qui n'utilisons pas Python dans le noir en ce qui concerne la structure de votre sortie désirée. Vous utilisez le terme "liste" mais la sortie suggère un ensemble ordonné de tuples.

Etant donné les conseils de @ chi, nous pourrions également suggérer d'utiliser la structure très "centrée sur R" de "dataframe"

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

... qui offre la flexibilité d'une liste en termes de types de colonne et les fonctionnalités d'accès d'une matrice en termes d'indexation de lignes et de colonnes. Vous pouvez également utiliser la demande de hhh et créer les valeurs implicitement indexées du vecteur j, 10:20, en utilisant le vecteur rownames qui commence à "1" par défaut, mais qui pourrait être modifié pour devenir un vecteur de caractère commençant à "0"

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

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

Malheureusement, les imprudents constateront que dfrm [0,] n’est pas un appel à part entière et renvoie un vecteur de longueur 0.

5
42-

Une autre option permettant de créer une liste de vecteurs consiste à utiliser la fonction Carte telle que vue ici par @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
1
wphampton

Pour utiliser les interprétations de liste de style Python avec des énumérations, telles que les listes énumérées, vous pouvez installer le package List-comprehension package LC (développé en 2018) et le package itertools (développé en 2015).

Liste des compréhensions dans R

Vous pouvez trouver le paquetage LCici .

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

Exemple

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

où la syntaxe de programmation n'est pas encore aussi nette et précise qu'en Python mais fonctionne fonctionnellement et son aide décrit:

"La syntaxe est la suivante: lc (expr, listes, prédicats) où expr est une expression à évaluer pour tous les éléments des listes, où Listes sont une ou plusieurs listes nommées, où elles sont spécifiées par un nom et une expression name = liste_expr, et où les prédicats sont des expressions qui doivent être évaluées en une valeur booléenne, par exemple, pour obtenir une liste de tous les nombres pairs, au carré, dans une liste x que nous pouvons écrire lc (x ** 2, x = x, x %% 2 == 0). Le résultat d'un appel à lc est une liste construite à partir des expressions dans expr, pour tous les éléments du fichier listes d'entrée où les prédicats sont évalués comme étant vrais. "

où notez que vous pouvez laisser les prédicats vides, par exemple dans l'exemple ci-dessus.

Outils et énumérations de style python

Vous pouvez utiliser les outils itertools de R qui sont très similaires aux outils itertools de Python, plus loin dans Cran here

library(itertools)

où décrit

"Divers outils permettant de créer des itérateurs, de nombreuses fonctions suivant le modèle dans le module Python itertools et d'autres, suivant le modèle de fonctions Du package 'snow'."

Exemple. énumération

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

Exemple. énumération avec 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"
0
hhh
# 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
    })
}
0
Leaf

Zip et enumerate ne sont pas particulièrement difficiles à mettre en œuvre dans R:

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

Énumérer est simple à définir en termes de Zip:

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

Etant donné que ce sont des fonctions appropriées, nous pouvons utiliser ... pour les rendre assez souples et concises, et tirer parti du comportement de mapply, tel que le recyclage des entrées et le nommage de la sortie.

0
Neal Fultz