Предварительно выделите ваше хранилище , прежде чем заполняет его циклом. Никогда делать то, что вы делаете, и объединять или r
| cbind
объекты внутри цикла.R должен копировать, выделять больше памяти и т. Д. На каждой итерации цикла, и это накладные расходы, которые наносят вред вашему коду.
Создайте Token.Count
с достаточным количеством строк и столбцов и заполните его в цикле.Что-то вроде:
Token.Count <- matrix(ncol = ?, nrow = nrow(Mydf))
for (i in seq_len(nrow(Mydf))) {
Token.Count[i, ] <- Myfun(i)
}
Token.Count <- data.frame(Token.Count)
Извините, я не могу быть более точным, но я не знаю, сколько столбцов Myfun
возвращает.
Обновление 1: Взглянув на textcnt
, я думаю, что вы, вероятно, можете вообще избежать цикла.У вас есть что-то вроде этого фрейма данных
DF <- data.frame(CumuCost = c(0.00439, 0.0067), Cost = c(1678, 880),
Keyword.text = c("north+face+outlet", "kinect sensor"),
stringsAsFactors = FALSE)
Если мы удаляем ключевые слова и преобразуем его в список
keywrds <- with(DF, as.list(Keyword.text))
head(keywrds)
Тогда мы можем вызвать textcnt
рекурсивно в этом списке для подсчета слов в каждом компоненте списка;
countKeys <- textcnt(keywrds, split = "[[:space:][:punct:]]+", method = "string",
n = 1L, recursive = TRUE)
head(countKeys)
- это почти то, что вы имели, за исключением того, что я добавил recursive = TRUE
для обработки каждого из входных векторов отдельно.Последний шаг - от sapply
функции sum
до countKeys
, чтобы получить количество слов:
> sapply(countKeys, sum)
[1] 3 2
Что, по-видимому, является тем, чего вы пытаетесь достичь с помощью цикла и функции.Я правильно понял?
Обновление 2: ОК, если исправлена проблема с предварительным распределением и , использованная textcnt
в векторизованном виде, по-прежнему нет 'не так быстро, как вы хотели бы, мы можем исследовать другие способы подсчета слов.Вполне возможно, что вам не нужны все функции textcnt
, чтобы делать то, что вы хотите.[Я не могу проверить, сработает ли приведенное ниже решение для всех ваших данных, но это намного быстрее.]
Одним из возможных решений является разделение вектора Keyword.text
на слова с использованием встроенного strsplit
функция, например, с использованием keywrds
, сгенерированного выше, и только первый элемент:
> length(unlist(strsplit(keywrds[[1]], split = "[[:space:][:punct:]]+")))
[1] 3
Чтобы использовать эту идею, возможно, проще обернуть ее в пользовательскую функцию:
fooFun <- function(x) {
length(unlist(strsplit(x, split = "[[:space:][:punct:]]+"),
use.names = FALSE, recursive = FALSE))
}
который мы затем можем применить к списку keywrds
:
> sapply(keywrds, fooFun)
[1] 3 2
Для этого простого примера набора данных мы получаем тот же результат.Как насчет времени вычислений?Сначала для решения используется textcnt
, объединяющее два шага из Обновление 1 :
> system.time(replicate(10000, sapply(textcnt(keywrds,
+ split = "[[:space:][:punct:]]+",
+ method = "string", n = 1L,
+ recursive = TRUE), sum)))
user system elapsed
4.165 0.026 4.285
, а затем решение для Обновление 2 :
> system.time(replicate(10000, sapply(keywrds, fooFun)))
user system elapsed
0.883 0.001 0.889
Так что даже для этой небольшой выборки при вызове textcnt
возникают значительные накладные расходы, но остается ли это различие при применении обоих подходов к полному набору данных.
Наконец, мы должны отметить, что подход strsplit
может быть векторизован для работы непосредственно с вектором Keyword.text
в DF
:
> sapply(strsplit(DF$Keyword.text, split = "[[:space:][:punct:]]+"), length)
[1] 3 2
, который дает те же результаты, что и два других подхода, инезначительно быстрее, чем не-векторизованное использование strsplit
:
> system.time(replicate(10000, sapply(strsplit(DF$Keyword.text,
+ split = "[[:space:][:punct:]]+"), length)))
user system elapsed
0.732 0.001 0.734
Является ли что-либо из этого более быстрым для вашего полного набора данных?
Незначительное обновление: репликацияDF
для получения 130 строк данных и синхронизации три подхода предполагают, что последний (векторизованный strsplit()
) масштабируется лучше:
> DF2 <- rbind(DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF)
> dim(DF2)
[1] 130 3
> system.time(replicate(10000, sapply(textcnt(keywrds2, split = "[[:space:][:punct:]]+", method = "string", n = 1L, recursive = TRUE), sum)))
user system elapsed
238.266 1.790 241.404
> system.time(replicate(10000, sapply(keywrds2, fooFun)))
user system elapsed
28.405 0.007 28.511
> system.time(replicate(10000, sapply(strsplit(DF2$Keyword.text,split = "[[:space:][:punct:]]+"), length)))
user system elapsed
7.497 0.011 7.528