Comments 21
Для тех, кто видит
data.table
впервые, рекомендую Руководство по data.table+2
Очень часто использую data.table — особенно при больших объемах данных. Есть еще интересный «побочный эффект»:
Т.е. в j можно практически все что угодно вычислять. И, если я не ошибаюсь, piping создает копии объектов, поэтому для DT правильнее использовать chaining.
data.table(x = seq(0, 6*pi, length.out = 1000)
)[, y := sin(x)
][, plot(y ~ x, type = "l", col = "blue")]
Т.е. в j можно практически все что угодно вычислять. И, если я не ошибаюсь, piping создает копии объектов, поэтому для DT правильнее использовать chaining.
+1
Очень часто использую data.table — особенно при больших объемах данных. Есть еще интересный «побочный эффект»:
Интересное замечание! Графики внутри ДТ я не строил, но в остальном полное взаимодействие с окружением, да. Испольвал также set и get внутри ДТ в родительское окружение.
И, если я не ошибаюсь, piping создает копии объектов, поэтому для DT правильнее использовать chaining.
Спасибо, я срочно почитаю про это. Не совсем уверен в ответе.
Оставлю это здесь — ДТ делает всегда копию при фильтрации в i, неважно каким стилем оформления кода это делается. Далее наступает вопрос, как gc работает с этими копиями. Вопрос не тривиальный, возился с проектами, где копии таблиц отжирали 30+ Гб оперативки, после оптимизации снизил до 10 Гб.
0
Со сборкой мусора — особенно при фрагментации — у R не очень. Еще интересно, возможно ли технически в DT организовать «внутренние» типы данных вроде float8, float16, int8 и т.д. В pandas/numpy это сильно помогает экономить память.
0
Со сборкой мусора — особенно при фрагментации — у R не очень.
Не уверен. Есть обсуждение этого вопроса подетальнее, ссылка на форум или SE?
Еще интересно, возможно ли технически в DT организовать «внутренние» типы данных вроде float8, float16, int8 и т.д. В pandas/numpy это сильно помогает экономить память.
Так как DT это по сути list, она использует аровские типы. Для 64-разрядного интежера я вроде ставил библиотеку, чтобы повысить с 32. Есть и другие трюки, но опять же на аровских типах. В принципе, это наверное вопрос к создателям ДТ, про такие фичи я ничего не слышал, думаю, нет этого.
По сравнению с богатством типов данных в numpy здесь проигрыш явный, да.
0
Да по типам вопрос не к вам — просто размышления вслух. В base R single == double: «R has no single precision data type». Но зато есть пакет float:
Вроде бы то что надо.
А на счет памяти: неоднократно была ситуация, когда удаляешь большой объект или его часть, запускаешь сборщик мусора, а память не освобождается.
> object.size(data.table(x=double(1000000)))
8001152 bytes
> object.size(data.table(x=float(1000000)))
4001768 bytes
Вроде бы то что надо.
А на счет памяти: неоднократно была ситуация, когда удаляешь большой объект или его часть, запускаешь сборщик мусора, а память не освобождается.
0
Интересно, интересно. Так не делал. Спасибо.
По памяти, да, понял. А вот так: попробуйте профайлер памяти (не времени) Rprof с записью памяти с очень дробным промежутком времени. Там видно, если конечно я ничего не перепутал, запуск gc очень часто.
А gc ведь очищает только точно не нужные участки памяти, например, дататейблы без ссылок на них. И вообще тог работает по своей логике, я ее не особо знаю… Может не удаляются объекты, которые он считает нужными? И может ошибается?
0
Для вытаскивания первой буквы можно ещё применить встроенную в data.table функцию разделения строк tstrsplit. По скорости будет примерно равно третьему варианту, но код гораздо проще :) Естественно это решение для конкретной задачи, а не для понимания, как делать быстро в целом.
dt[, first_l := NULL]
microbenchmark({
dt[, first_l := tstrsplit(w, split = ' ', fixed = T, keep = 1L)]
})
+1
Да, согласен. ) Но я хотел показать, что когда есть, например, текст из разных слов или стринга с различными значениями, разделенными пробелом, как это дело спарсить. Но для буквы ваш вариант должен быть идеальным. )
0
Добавил в раздел про векторизацию более реальный пример. Там тоже делается векторизация через strsplit, и она реально нужна.
0
По моему с новым примером что-то не то. Функция first_l_f3 не используется в коде, а только создаётся.
И выдаётся такая ошибка
И выдаётся такая ошибка
dt[
, (paste0('w_', 1:3)) := strsplit(w, split = ' ', fixed = T)
]
Error in `[.data.table`(dt, , `:=`((paste0("w_", 1:3)), strsplit(w, split = " ", :
Supplied 3 columns to be assigned 100000 items. Please see NEWS for v1.12.2.
+1
Сори, Код не обновил… Скоро обновлю, посмотрите.
0
Спасибо, что заметили. Обновил код в статье.
microbenchmark({
dt[
, (paste0('w_', 1:3)) := lapply(1:3, function(x) first_l_f3(w, x))
]
})
0
Мне кажется Вы опять усложнили решение не используя встроенные функции.
В Вашем варианте получается, что одно и тоже разделение на слова происходит три раза?
Я бы сделал функцией, которую предлагал выше
у меня это работает в 5 раз быстрее.
Кстати функция str_split из stringr позволяет получать на выходе матрицу и можно её использовать
В Вашем варианте получается, что одно и тоже разделение на слова происходит три раза?
Я бы сделал функцией, которую предлагал выше
dt[, (paste0('w_', 1:3)) := NULL]
microbenchmark({
dt[, (paste0('w_', 1:3)) := tstrsplit(w, split = ' ', fixed = T, keep = 1L:3L)]
})
у меня это работает в 5 раз быстрее.
Кстати функция str_split из stringr позволяет получать на выходе матрицу и можно её использовать
library(stringr)
dt[, (paste0('w_', 1:3)) := NULL]
microbenchmark({
cbind(dt, str_split(dt$w, " ", simplify = TRUE)[, 1:3])
})
+2
Вы верно ухватили смысл. Все так и есть. Рад, что нашли более крутое решение! Завтра попробую его. tstrsplit? Это из библиотеки?
0
Заслуженные лайки. Код обновил.
0
Sign up to leave a comment.
Вокруг data.table