Zip veya R'de numaralandırma?


84

Bu Python liste anlayışları için R eşdeğerleri nelerdir:

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

Çıkışlı Örnek

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

Bu sorunu daha önce R'de bir numara ile çözmüştüm ama artık hatırlayamıyorum, ilk fikir itertools -pkg idi, ancak işleri yapmanın daha deyimsel bir yolunu bulmayı umuyorum.


2
Python'a aşina olmayanlarımız için çalışılmış küçük bir örnek verebilirseniz, potansiyel cevaplayıcıların nüfusunu artırabilir. Sanırım sonuncusuexpand.grid(i=10:20,j=10:20)
Ben Bolker

@BenBolker: bir çıktı ekledi - şimdi açık mı? Daha zor olabilir ama mantık önemli ...
hhh

1
@DWin'e katılıyorum. R ve Python'daki veri yapıları arasında bire bir eşleştirme beklemek mantıksızdır. İyi cevaplar istiyorsanız, sonucun Python'da değil R'de nasıl görünmesini istediğinizi belirtmelisiniz .
joran

Bu arada, işte iki listeyi as.vector(rbind(1:10, 11:20))
sıkıştırmanın

Yanıtlar:


47

Python için cevap enumerate:

R'de bir liste sıralanır ( bu cevaba bakın ). Bu nedenle, ihtiyacınız olan tek şey anahtarları (kullanarak names()[i]) veya değerleri (kullanarak [[i]]) indekslemektir .

Kullanarak seq_along(alternatif olarak yapabilir 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 için cevap zip:

Tuple listesini taklit etmek için yukarıdaki cevaplardan birine bakın. Tercihim BondedDust'ın cevabında gösterildiği gibi bir veri çerçevesine doğru:

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

1
İlk örneğinizi ikinciye devam ettirmek için,data.frame(names=labels(mylist),values=unlist(mylist),row.names = 1:length(mylist))
Josiah Yoder

performansla ilgili bir soru: isimleri çağırmak (mylist) [i] her seferinde çalışmak zorunda mı yoksa önemsiz bir işlem mi? Döngüden önce name_list'e atamanın en iyisi olup olmadığını merak ediyorum
markgalassi

42

R için liste anlama konusunda bazı tartışmalar oldu, örneğin burada veya orada . Karma paket bile sözlük benzeri yapıya sahiptir. Bununla birlikte, diğerlerinin dediği gibi, neye alışması gerektiğine dair net bir anlayış olmadan bir dil imkanını diğeriyle eşleştirmeye çalışmak zordur (programlama dillerinin karşılaştırmasının aslında sunduğu şey bu olsa bile ). Örneğin, zip()R'de Python'u aşağıdaki gibi taklit edebilirim :

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 

Görüldüğü gibi, bu gerçekten daha sonra sonuçla ne yapmak istediğinize bağlı.


1
Sanırım soru, zip'i python'da kullandığınızda ne kullanacağınız. tipik kullanım, birden çok bağımsız değişkenle bir liste kavrama yapmaktır, bu nedenle mapply bunu doğrudan halleder.
seanv507

6
mapplyBiz doğrudan analog için istiyoruz.
StephenBoesch

@javadba mapplyen yaygın kullanım durumunu kapsar: zip ve ardından eşleme.
Josiah Yoder

8

Vektörlerin bir listesini oluşturacak başka bir seçenek de @peterhurford tarafından görüldüğü gibi Harita işlevini kullanmaktır: 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'da, fermuann birincil kullanımı pek çok vektör / listeler üzerinde yineleme: for xi, yi in zip(x, y): .... Bunu R'de yapmak için şimdiye kadar gördüğüm en zarif çözüm için +1:for (xi.yi in Map(c, x, y)) { xi <- xi.yi[1]; yi <- xi.yi[2]; ... }
sgrubsmyon

6

Bu bir matrisin Python baskı temsiliyse, o zaman şu kod:

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

Siz hala Python kullanıcısı olmayanları, istediğiniz çıktının yapısı konusunda karanlıkta bırakıyorsunuz. "Liste" terimini kullanırsınız, ancak çıktı, sıralı bir demet kümesi önerir.

@ Chi'nin rehberliği göz önüne alındığında, R merkezli 'veri çerçevesi' yapısının kullanılmasını da önerebiliriz

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

... sütun türleri açısından bir liste esnekliğine ve satır ve sütun indeksleme açısından bir matrisin erişim özelliklerine sahip olan. Veya hhh'nin isteği 10:20kullanılabilir ve rownamesvarsayılan olarak "1" ile başlayan, ancak "0" dan başlayan bir karakter vektörü haline getirilebilecek vektörü kullanarak j-vektörünün örtük olarak indekslenmiş değerlerini yaratabilir.

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

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

Ne yazık ki, dikkatsiz olan kişi dfrm [0,] 'nin 0 uzunluğunda dönen vektörün mutlu bir çağrı olmadığını görecektir.


Zarif bir çözüm için +1. (Hayır, bunlar Python matrisleri değil, daha önce tahmin ettiğiniz gibi tuple listesi .)
chl

4

Numaralandırılmış listeler gibi numaralandırmalarla Python tarzı liste anlayışlarını kullanmak için bir yol, Liste anlama paketi LC(geliştirilmiş 2018) ve itertools paketi (2015 geliştirilmiştir) kurmaktır.

R'de anlamaları listeleyin

LCPaketi burada bulabilirsiniz .

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

Misal

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

programlama sözdiziminin henüz Python'daki kadar temiz ve parlak olmadığı, ancak işlevsel olarak çalıştığı ve yardımının ana hatları:

"Sözdizimi şu şekildedir: lc (ifade, listeler, yüklemler) burada ifade, listelerdeki tüm öğeler için değerlendirilecek bir ifadedir, burada listeler bir veya daha fazla adlandırılmış listedir, burada bunlar bir ad ve bir ifade adıyla belirtilir = list_expr ve burada tahminler, bir boole değeri olarak değerlendirilmesi gereken ifadelerdir.Örneğin, bir x listesinden tüm çift sayıların karesi alınmış bir liste almak için lc (x ** 2, x = x, x% % 2 == 0). Lc çağrısının sonucu, tahminlerin doğru olarak değerlendirildiği girdi listelerindeki tüm öğeler için ifade içindeki ifadelerden oluşturulan bir listedir. "

Örneğin yukarıdaki örnekte yüklemleri boş bırakabileceğinize dikkat edin.

Python tarzı yinelemeler ve numaralandırmalar

Python'un itertools'una çok benzeyen R'nin itertool'larını, daha sonra Cran'da kullanabilirsiniz .

library(itertools)

tarif edildiği yerde

"Yineleyiciler oluşturmak için çeşitli araçlar, birçoğu Python itertools modülündeki ardışık işlevler ve diğerleri 'kar' paketindeki işlevlerden sonra desenlenmiştir."

Misal. sayım

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

Misal. ZIP ile numaralandırma

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

4

zipve enumerateR'de uygulanması özellikle zor değildir:

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

Numaralandırmanın tanımlanması basittir zip:

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

Bunlar uygun işlevler olduğundan, ...onları oldukça esnek ve özlü hale getirmek için kullanabiliriz ve girdileri geri dönüştürme ve çıktıları doğru şekilde adlandırma gibi mapply'nin davranışından yararlanabiliriz.


1
Bunlar stackoverflowpakete eklendi , fwiw.
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
    })
}

Lütfen bu kod bloğunun ne yaptığı hakkında bir açıklama sağlayın.
Keivan Esbati

bu işlev, @chl'nin işaret ettiği "mapply (list, x, y, SIMPLIFY = F)" ile tamamen aynı şeyi yapar
ibilgen

0

Bu, iki yapıştırma ifadesi kullanılarak elde edilebilir:

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

Çıktı aşağıdaki gibi olacaktır:

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

0

Python için, R'deki eşdeğeri 'numaralandı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))
}

Çıktı:

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

R 'liste' vektörleri yatırmak ve bir endeksle tutmak için güzel bir bankadır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.