У меня есть вектор имен:
names <- c("a", "b", "c", "d", "e", "f", "g", "h")
Я хочу составить серию комбинаций этих имен с этими числами соответственно:
numbers <- c(0, 0:2, 0:3, 0:1, 0:1, 0, 0, 0)
Итак, мои комбинации будут:
a0 b0 b1 b2 c0 c1 c2 c3 d0 d1 e0 e1 f0 g0 h0
Как мне это сделать? Я предпочитаю использовать векторизованную функцию, чем итерацию.
Я попробовал эти коды, но получил неверные результаты (возможно, из-за перезарядки или чего-то еще):
paste0(names, numbers, recycle0 = F)
paste0(names, numbers, recycle0 = T)
paste0(names, numbers |> as.list())
purrr::map_chr(names, paste0(c(0, 0:2, 0:3, 0:1, 0:1, 0, 0, 0)))
и еще несколько, которые я точно не помню.
Вот решение, использующее numbers
в качестве вектора с максимальной последовательностью.
names <- c("a", "b", "c", "d", "e", "f", "g", "h")
numbers <- c(0, 2, 3, 1, 1, 0, 0, 0)
library(purrr)
unlist(map2(.x = names,.y = numbers,.f = \(.x,.y) paste0(.x,0:.y)))
[1] "a0" "b0" "b1" "b2" "c0" "c1" "c2" "c3" "d0" "d1" "e0" "e1" "f0" "g0" "h0"
Можете ли вы использовать Mapply:
names <- c("a", "b", "c", "d", "e", "f", "g", "h")
numbers <- list(0, 0:2, 0:3, 0:1, 0:1, 0, 0, 0)
unlist(mapply(function(name, nums) paste0(name, nums), names, numbers))
Выход:
a b1 b2 b3 c1 c2 c3 c4 d1 d2 e1 e2 f g h
"a0" "b0" "b1" "b2" "c0" "c1" "c2" "c3" "d0" "d1" "e0" "e1" "f0" "g0" "h0"
нет, неправильно прочитал документацию. R docs, не хватает ngl.
1) cumsum(...)
— это индексы имен, т. е. 1 2 2 2 3 3 3 3 4 4 5 5 6 7 8, поэтому индексируйте names
и вставьте numbers
в конец. Никакие внешние пакеты не используются.
paste0(names[cumsum(numbers == 0)], numbers)
## [1] "a0" "b0" "b1" "b2" "c0" "c1" "c2" "c3" "d0" "d1" "e0" "e1" "f0" "g0" "h0"
2) Второй подход, также основанный на cumsum(...)
, заключается в том, чтобы использовать rle
для получения длины пробега, повторять каждое имя указанное количество раз, а затем вставлять числа. При этом также не используются пакеты.
paste0(rep(names, rle(cumsum(numbers == 0))$lengths), numbers)
## [1] "a0" "b0" "b1" "b2" "c0" "c1" "c2" "c3" "d0" "d1" "e0" "e1" "f0" "g0" "h0"
2a) Немного более короткий вариант — использовать table
вместо rle(...)$lengths
:
paste0(rep(names, table(cumsum(numbers == 0))), numbers)
3) Этот не использует cumsum
, но использует пакет. В numbers
замените 0 на имена, а остальные цифры на NA. Затем используйте na.locf0
, чтобы заполнить NA и вставить цифры.
library(zoo)
paste0(na.locf0(replace(NA * numbers, numbers == 0, names)), numbers)
## [1] "a0" "b0" "b1" "b2" "c0" "c1" "c2" "c3" "d0" "d1" "e0" "e1" "f0" "g0" "h0"
Ввод из вопроса
names <- c("a", "b", "c", "d", "e", "f", "g", "h")
numbers <- c(0, 0:2, 0:3, 0:1, 0:1, 0, 0, 0)
Нужна ли здесь SIMPLIFY?