Ответ 1
Возможно, вы помните data.table FAQ 2.17, который содержит:
stringsAsFactors по умолчанию TRUE в data.frame, но FALSE в data.table, для эффективности. Поскольку к R добавлен глобальный кеш строк, элементы символов являются указателями на одну кешированную строку, и больше нет преимущества для преобразования в коэффициент.
(Эта часть была добавлена в FAQ в v1.8.2 в июле 2012 года.)
Использование символа, а не фактора помогает в таких задачах, как укладка (rbindlist). Так как a c()
двух символьных векторов - это просто конкатенация, тогда как a c()
двух столбцов факторов необходимо пересечь и объединить два уровня факторов, которые сложнее кодировать и выполнять больше времени.
Что вы заметили, это разница в потреблении ОЗУ на 64-битных машинах. Факторы хранятся в виде векторного поиска integer
элементов на уровнях. Тип integer
- 32 бит, даже на 64-битных платформах. Но указатели (какой вектор character
) являются 64-битными на 64-битных машинах. Таким образом, столбец символов будет использовать вдвое больше оперативной памяти, чем столбцы факторов на 64-битной машине. Нет разницы на 32 бит. Однако обычно эта стоимость будет перевешиваться более быстрыми и более быстрыми инструкциями по символьному вектору. [Кроме того, поскольку факторы integer
, они не могут содержать более 2 миллиардов уникальных строк. Столбцы character
не имеют этого ограничения.]
Это зависит от того, что вы делаете, но операции оптимизированы для character
в data.table и так, что мы советуем. В основном это экономит прыжок (до уровней), и мы можем сравнивать два столбца символов в разных таблицах, просто сравнивая значения указателя без скачкообразного перехода даже в глобальный кеш.
Это зависит от мощности столбца. Скажем, столбец составляет 1 миллион строк и содержит 1 миллион уникальных строк. Для хранения в качестве фактора потребуется 1 миллион векторных символов для уровней плюс 1 миллион целых векторов, указывающих на элементы уровня. Это (4 + 8) * 1e6 байт. С другой стороны, для символьного вектора не нужны уровни, а всего 8 * 1e6 байт. В обоих случаях глобальный кеш хранит 1 миллион уникальных строк таким же образом, чтобы это происходило в любом случае. В этом случае столбец символов будет использовать меньше ОЗУ, чем если бы он был фактором. Будьте осторожны, чтобы проверить, что инструмент памяти, используемый для вычисления использования ОЗУ, вычисляет это соответствующим образом.