Может ли кто-нибудь помочь мне сделать этот код R более эффективным?
Я пытаюсь написать функцию, которая изменяет список строк на вектор строк или список чисел на вектор чисел, списков типизированных элементов на векторы определенного типа в целом.
Я хочу иметь возможность изменять списки на определенный тип вектора, если они имеют следующие свойства:
Они однотипны. Каждый элемент списка имеет тип «символ», «сложный» и т. д.
Каждый элемент списка имеет длину один.
as_atomic <- local({ assert_is_valid_elem <- function (elem, mode) { if (length(elem) != 1 || !is(elem, mode)) { stop("") } TRUE } function (coll, mode) { if (length(coll) == 0) { vector(mode) } else { # check that the generic vector is composed only # of length-one values, and each value has the correct type. # uses more memory that 'for', but is presumably faster. vapply(coll, assert_is_valid_elem, logical(1), mode = mode) as.vector(coll, mode = mode) } } })
Например,
as_atomic(list(1, 2, 3), 'numeric')
as.numeric(c(1,2,3))
# this fails (mixed types)
as_atomic( list(1, 'a', 2), 'character' )
# ERROR.
# this fails (non-length one element)
as_atomic( list(1, c(2,3,4), 5), 'numeric' )
# ERROR.
# this fails (cannot convert numbers to strings)
as_atomic( list(1, 2, 3), 'character' )
# ERROR.
Приведенный выше код работает нормально, но он очень медленный, и я не вижу способа оптимизировать его без изменения поведения функции. Важно, чтобы функция as_atomic вела себя так, как она; Я не могу переключиться на знакомую мне базовую функцию (например, удалить список), так как мне нужно выдать ошибку для плохих списков.
require(microbenchmark)
microbenchmark(
as_atomic( as.list(1:1000), 'numeric'),
vapply(1:1000, identity, integer(1)),
unit = 'ns'
)
На моей (довольно быстрой) машине тест имеет частоту около 40 Гц, поэтому эта функция почти всегда ограничивает скорость в моем коде. Бенчмарк vapply control имеет частоту около 1650 Гц, что все еще довольно медленно.
Есть ли способ резко повысить эффективность этой операции? Любые советы приветствуются.
Если необходимы какие-либо разъяснения или правки, пожалуйста, оставьте комментарий ниже.
Редактировать:
Всем здравствуйте,
Извините за очень запоздалый ответ; У меня были экзамены, которые мне нужно было пройти, прежде чем я мог попытаться повторно реализовать это.
Спасибо всем за советы по производительности. Я поднял производительность с ужасных 40 Гц до более приемлемых 600 Гц, используя простой код R.
Наибольшее ускорение было от использования typeof или режима вместо is; это действительно ускорило тесный внутренний цикл проверки.
Мне, вероятно, придется стиснуть зубы и переписать это в rcpp, чтобы сделать его действительно производительным.
as.numeric(list(1,2,3))
? илиas.character
... - person agstudy   schedule 19.03.2014list(1, 'a', 2)
? - person agstudy   schedule 19.03.2014