Первая проблема: as.list
работает только с первым аргументом, поэтому ваш date
выглядит как "JANUARY"
. Чтобы решить эту проблему, используйте dat <- list(...)
.
as.list(1,2,3)
# [[1]]
# [1] 1
list(1,2,3)
# [[1]]
# [1] 1
# [[2]]
# [1] 2
# [[3]]
# [1] 3
Во-вторых, это что-то вроде «внешнего соединения», в котором вы хотите, чтобы каждый первый вектор был в паре с каждым из второго вектора. Функция outer
делает что-то подобное с двумя свойствами:
Ее возвращаемое значение равно matrix
, что не всегда является необходимым. См. outer(1:3, 4:5,
*)
, чтобы увидеть, как это выглядит.
Он предлагает расширение и вызывает функцию один раз , поэтому мы можем видеть, что все выглядит примерно так:
outer(1:3, 4:5, function(a, b) { browser(); a*b; })
# Called from: FUN(X, Y, ...)
debug at #1: a * b
a
# [1] 1 2 3 1 2 3
b
# [1] 4 4 4 5 5 5
Может быть, проще увидеть пары следующим образом:
cbind(a,b)
# a b
# [1,] 1 4
# [2,] 2 4
# [3,] 3 4
# [4,] 1 5
# [5,] 2 5
# [6,] 3 5
Таким образом, наша операция должна иметь возможность обрабатывать все данные одновременно.
a*b
# [1] 4 8 12 5 10 15
Часто функции (вашему clean
) требуется одиночный знак в каждом аргументе, поэтому outer
не всегда работает хорошо.
Альтернатива это использовать expand.grid
.
eg <- expand.grid(date = date, type = type, stringsAsFactors = FALSE)
eg
# date type
# 1 JANUARY Education
# 2 FEBRUARY Education
# 3 JANUARY Government
# 4 FEBRUARY Government
Отсюда, есть несколько подходов, в зависимости от вашего мастерства и предпочтений элегантности. mapply
аналогичен sapply
в том, что он пытается вернуть упрощенную структуру, но он принимает функцию с произвольным числом векторов / списков:
mapply(function(a, b) paste(a, b, sep = ","), eg$date, eg$type)
# [1] "JANUARY,Education" "FEBRUARY,Education" "JANUARY,Government" "FEBRUARY,Government"
или Map
, вариант, который всегда возвращает list
(это мое предпочтение, поскольку мне нравится знать , что возвращается):
Map(function(a, b) paste(a, b, sep = ","), eg$date, eg$type)
# [[1]]
# [1] "JANUARY,Education"
# [[2]]
# [1] "FEBRUARY,Education"
# [[3]]
# [1] "JANUARY,Government"
# [[4]]
# [1] "FEBRUARY,Government"
В вашем случае это может быть просто out <- Map(clean, eg$date, eg$type)
.
Однако некоторые люди предпочитают петли for
, и поэтому эквивалент выглядит примерно так:
for (i in seq_len(nrow(eg))) {
print(paste(eg$date[i], eg$type[i], sep = ","))
}
# [1] "JANUARY,Education"
# [1] "FEBRUARY,Education"
# [1] "JANUARY,Government"
# [1] "FEBRUARY,Government"
### your equivalent:
for (i in seq_len(nrow(eg))) {
clean(eg$date[i], eg$type[i])
}
Чтобы увидеть, как Map
(и mapply
), может быть полезно «развернуть» происходящее. Если я сделаю Map(paste, eg$date, eg$type)
(а списки будут длиннее, скажем, длина n
), тогда он действительно сделает
paste(eg$date[1], eg$type[1])
paste(eg$date[2], eg$type[2])
...
paste(eg$date[n], eg$type[n])
и обернет каждое возвращаемое значение в list
(для Map
) или vector
(для mapply
, если данные одного типа / форма / длина / тусклый /...).