Zip или перечислить в R?
Каковы R-эквиваленты для этих списков 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
Пример с выходом
>>> [(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, но я надеюсь найти более идиоматический способ делать что-то.
Ответы
Ответ 1
Были высказаны некоторые дискуссии по поводу понимания списка для R, например. здесь или там. Пакет hash предлагает даже словарно-подобную структуру. Однако, как говорили другие, трудно попытаться сопоставить языковые средства на другом (даже если это то, что предлагает сравнение языков программирования) без четкого понимания к чему он должен привыкнуть. Например, я могу имитировать Python 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
Как видно, это действительно зависит от того, что вы хотите сделать после результата.
Ответ 2
Ответ для 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
Ответ 3
Если это представление печати 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-центрическую структуру 'dataframe'
x <- 1:3
y <- 4:6
dfrm <- data.frame(x=x, y=y)
... который обладает гибкостью списка в терминах типов столбцов и функций доступа матрицы в терминах индексирования строк и столбцов. Или можно использовать запрос hhh и создать неявно проиндексированные значения j-vector, 10:20
, используя вектор rownames
, который начинается с "1" по умолчанию, но который может быть изменен, чтобы стать символьным вектором, начинающимся с символа "0"
dfrm <- data.frame(j=10:20)
dfrm[3, ]
#[1] 12
rownames(dfrm) <- 0:10
dfrm["0",]
# [1] 10
К сожалению, неосторожный найдет, что dfrm [0,] не является счастливым вызовом, возвращающим вектор длины 0.
Ответ 4
Другой вариант, который создаст список векторов, - это использовать функцию 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
Ответ 5
Чтобы использовать списки в стиле Python с перечислениями, такими как перечислимые списки, одним из способов является установка пакета 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. "
где обратите внимание, что вы можете оставить предикаты пустыми, например, в приведенном выше примере.
Itertools и перечисления в стиле Python
Вы можете использовать R itertools, который очень похож на Python 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"
Ответ 6
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), ...)
}
Так как это правильные функции, мы можем использовать ...
, чтобы сделать их достаточно гибкими и краткими, и использовать преимущества картографического поведения, такого как правильная переработка входных данных и правильное именование выходных данных.
Ответ 7
# 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
})
}