Если вы хотите, чтобы сервер MySQL решал набор символов, а не PHP как клиент (старое поведение, предпочтительнее, на мой взгляд), попробуйте добавить skip-character-set-client-handshake
к вашему my.cnf
в [mysqld]
и перезапустить mysql
.
Это может вызвать проблемы, если вы используете что-либо, кроме UTF8.
Да, вы здесь под вопросом:
Я понимаю, что более эффективно перебирать вектор имен столбцов, используя
:=
для назначения:blockquote>
for (col in paste0("V", 20:100)) dt[, col := sqrt(dt[[col]]), with = FALSE]
Кроме того: обратите внимание, что новый способ сделать это:
for (col in paste0("V", 20:100)) dt[ , (col) := sqrt(dt[[col]])]
, потому что
with = FALSE
было непросто прочитать, относится к LHS или RHS:=
. Конец.Как вы знаете, это эффективно, потому что каждый столбец один за другим, поэтому рабочая память нужна только для одного столбца за раз. Это может сделать разницу между работой и ошибкой с ошибкой ошибки вне памяти.
Проблема с
lapply
в RHS:=
заключается в том, что RHS (lapply
) оценивается первым; то есть результат для 80 столбцов. Это 80 колонок стоит новой памяти, которая должна быть распределена и заполнена. Таким образом, для достижения этой цели вам понадобится бесплатная операционная память 80 столбцов. Это использование ОЗУ доминирует против мгновенной операции назначения ( plonking ) этих 80 новых столбцов в слоты указателя столбца data.table.Как отметил @Frank, если у вас есть много столбцов (скажем, 10 000 или более), тогда небольшие накладные расходы на отправку методу
[.data.table
начинают складываться). Чтобы устранить эти служебные данные, которые естьdata.table::set
, которые под?set
описываются как «закодированные»:=
. Я использую циклfor
для этого типа операции. Это самый быстрый способ и довольно легко писать и читать.for (col in paste0("V", 20:100)) set(dt, j = col, value = sqrt(dt[[col]]))
Хотя с 80 столбцами это вряд ли имеет значение. (Обратите внимание, что это может быть более распространено для цикла
set
для большого количества строк, чем большое количество столбцов.) Однако циклset
не решает проблему повторной ссылки на имя символаdt
, которое вы упомянули в вопросе:Мне это не нравится, потому что мне не нравится ссылаться на data.table в выражении aj.
blockquote>Согласовано. Поэтому лучше всего вернуться к вашему циклу
:=
, но вместо этого используйтеget
.for (col in paste0("V", 20:100)) dt[, (col) := sqrt(get(col))]
Однако я боюсь, что использование
get
вj
может быть неэффективным. Для этого необходим бенчмаркинг, # 1380 . Кроме того, возможно, смущает использованиеget()
в RHS, но не на LHS. Чтобы решить, что мы можем сахара LHS и разрешитьget()
, # 1381 :for (col in paste0("V", 20:100)) dt[, get(col) := sqrt(get(col))]
Кроме того, возможно
value
ofset
можно запустить в пределах область действияDT
, # 1382 .for (col in paste0("V", 20:100)) set(dt, j = col, value = sqrt(get(col))
Они должны работать, если вы хотите ссылаться на столбцы по имени строки:
n = paste0("V", 20:100)
dt[, (n) := lapply(n, function(x) {sqrt(get(x))})]
или
dt[, (n) := lapply(n, function(x) {sqrt(dt[[x]])})]
Это то, что вы ищете?
dt[ , names(dt)[20:100] :=lapply(.SD, function(x) sqrt(x) ) , .SDcols=20:100]
Я слышал, что использование .SD
не так эффективно, потому что оно делает копию таблицы заранее, но если ваша таблица не является " t огромный (очевидно, это относительно зависит от ваших системных спецификаций). Я сомневаюсь, что это будет иметь большое значение.