Was sind die R-Äquivalente für diese Python-Listenverständnisse:
[(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
Beispiel mit Ausgabe
>>> [(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)]
Ich habe dieses Problem früher mit einem Trick in R gelöst, kann mich aber nicht mehr erinnern. Die erste Idee war itertools -pkg, aber ich hoffe, eine idiomatischere Art zu finden, Dinge zu tun.
expand.grid(i=10:20,j=10:20)
as.vector(rbind(1:10, 11:20))
Antworten:
Antwort für Python
enumerate
:In R ist eine Liste geordnet (siehe diese Antwort ). Sie müssen also nur entweder Schlüssel (using
names()[i]
) oder Werte (using[[i]]
) indizieren .Verwenden
seq_along
(alternativ kannfor(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"
Antwort für Python
zip
:Sehen Sie sich eine der obigen Antworten an, um die Liste der Tupel nachzuahmen. Ich bevorzuge einen Datenrahmen, wie in der Antwort von BondedDust gezeigt:
> x <- 1:3 > y <- 4:6 > data.frame(x=x, y=y) x y 1 1 4 2 2 5 3 3 6
quelle
data.frame(names=labels(mylist),values=unlist(mylist),row.names = 1:length(mylist))
Es gab einige Diskussionen über das Listenverständnis für R, z . B. hier oder da . Das Hash- Paket bietet sogar eine wörterbuchartige Struktur. Wie andere sagten, ist es jedoch schwierig zu versuchen, eine Spracheinrichtung einer anderen zuzuordnen (selbst wenn dies der Vergleich von Programmiersprachen tatsächlich bietet), ohne ein klares Verständnis dafür zu haben, woran es gewöhnt sein soll. Zum Beispiel kann ich Python
zip()
in R wie folgt nachahmen :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
Wie zu sehen ist, hängt dies wirklich davon ab, was Sie anschließend mit dem Ergebnis machen möchten.
quelle
mapply
wollen wir für das direkte Analog.mapply
behandelt den häufigsten Anwendungsfall: zip, dann map.Eine weitere Option, mit der eine Liste von Vektoren erstellt wird, ist die Verwendung der Map-Funktion, wie sie hier von @peterhurford angezeigt wird: 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
quelle
for xi, yi in zip(x, y): ...
. +1 für die eleganteste Lösung, die ich bisher gesehen habe, um dies in R:for (xi.yi in Map(c, x, y)) { xi <- xi.yi[1]; yi <- xi.yi[2]; ... }
Wenn dies die Python-Druckdarstellung einer Matrix ist, dann dieser 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
Sie lassen diejenigen von uns, die keine Python-Benutzer sind, immer noch im Dunkeln, was die Struktur Ihrer gewünschten Ausgabe betrifft. Sie verwenden den Begriff "Liste", aber die Ausgabe schlägt einen geordneten Satz von Tupeln vor.
In Anbetracht der Anleitung von @ chi könnten wir auch vorschlagen, die sehr R-zentrierte 'Datenrahmen'-Struktur zu verwenden
x <- 1:3 y <- 4:6 dfrm <- data.frame(x=x, y=y)
... die die Flexibilität einer Liste in Bezug auf Spaltentypen und die Zugriffsfunktionen einer Matrix in Bezug auf die Zeilen- und Spaltenindizierung aufweist. Oder man könnte die Anfrage von hhh verwenden und die implizit indizierten Werte des j-Vektors erstellen
10:20
, wobei derrownames
Vektor verwendet wird, der standardmäßig bei "1" beginnt, der jedoch geändert werden kann, um ein Zeichenvektor zu werden, der bei "0" beginnt.dfrm <- data.frame(j=10:20) dfrm[3, ] #[1] 12 rownames(dfrm) <- 0:10 dfrm["0",] # [1] 10
Leider wird der Unvorsichtige feststellen, dass dfrm [0,] kein glücklicher Aufruf ist und einen Vektor der Länge 0 zurückgibt.
quelle
Um Listenverständnisse im Python-Stil mit Aufzählungen wie Aufzählungslisten zu verwenden, besteht eine Möglichkeit darin, das Listenverständnispaket
LC
(entwickelt 2018) und das itertools-Paket (entwickelt 2015) zu installieren .Listenverständnisse in R.
Das
LC
Paket finden Sie hier .install.packages("devtools") devtools::install_github("mailund/lc")
Beispiel
> 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"
wo die Programmiersyntax noch nicht so sauber und poliert ist wie in Python, aber funktional funktioniert und ihre Hilfe beschreibt:
Beachten Sie, dass Sie die Prädikate beispielsweise im obigen Beispiel leer lassen können.
Itertools und Aufzählungen im Python-Stil
Sie können R itertools verwenden, die Pythons itertools sehr ähnlich ist, weiter in Cran hier
wo beschrieben
Beispiel. Aufzählung
> 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"
Beispiel. Aufzählung mit 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"
quelle
zip
undenumerate
sind in R nicht besonders schwer zu implementieren:#' zip(1:5,1:10) zip <- function(...) { mapply(list, ..., SIMPLIFY = FALSE) }
Aufzählen ist einfach zu definieren in Bezug auf
zip
:#' enumerate(l=LETTERS) enumerate <- function(...) { zip(ix=seq_along(..1), ...) }
Da es sich um ordnungsgemäße Funktionen handelt, können wir sie verwenden
...
, um sie ziemlich flexibel und knapp zu gestalten und das Verhalten von Mapply zu nutzen, z. B. das Recycling von Eingaben und die korrekte Benennung von Ausgaben.quelle
stackoverflow
Paket fwiw hinzugefügt.# 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 }) }
quelle
Dies kann mit zwei Einfügeanweisungen erreicht werden:
str1 <- paste(1:11, 10:20, sep=",", collapse='), (') paste("(", str1, ")", sep = "")
Die Ausgabe wird wie folgt aussehen:
'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'
quelle
Für Python sollte das Äquivalent 'aufzählen' in R. Das Speichern der Vektoren in der Liste und das Durchlaufen mit einem Index sollte funktionieren.
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)) }
Ausgabe:
[1] "1" "A" "a" [1] "2" "B" "b" [1] "3" "C" "c"
R 'list' ist eine nette Bank, um die Vektoren einzuzahlen und mit einem Index zu behalten.
quelle