Во-первых, вы пишете, что:
Затем мне нужно транспонировать этот набор данных для правильной подгруппы позже,
Если честно, я сомневаюсь, что у вас естьк.Таким образом, это может быть XY-проблемой.Тем не менее, я думаю, что может представлять общий интерес для анализа проблемы.
Увеличение размера объекта, скорее всего, связано с тем, что class
объекта до и после транспонирования изменились вместес тем, что объекты разных классов имеют разный размер.
Я попытаюсь проиллюстрировать это на нескольких примерах.Мы начинаем со смены класса.
Создаем игрушечный фрейм данных со структурой, напоминающей вашу, с несколькими столбцами символов и несколькими числовыми столбцами:
# set number of rows and columns
nr <- 5
nc <- 5
set.seed(1)
d <- data.frame(x = sample(letters, nr, replace = TRUE),
y = sample(letters, nr, replace = TRUE),
matrix(runif(nr * nc), nrow = nr),
stringsAsFactors = FALSE)
Транспонируем его:
d_t <- t(d)
Проверьте str
текст исходных данных и их транспонированного брата:
str(d)
# 'data.frame': 5 obs. of 7 variables:
# $ x : chr "g" "j" "o" "x" ...
# $ y : chr "x" "y" "r" "q" ...
# $ X1: num 0.206 0.177 0.687 0.384 0.77
# $ X2: num 0.498 0.718 0.992 0.38 0.777
# $ X3: num 0.935 0.212 0.652 0.126 0.267
# $ X4: num 0.3861 0.0134 0.3824 0.8697 0.3403
# $ X5: num 0.482 0.6 0.494 0.186 0.827
str(d_t)
# chr [1:7, 1:5] "g" "x" "0.2059746" "0.4976992" ...
# - attr(*, "dimnames")=List of 2
# ..$ : chr [1:7] "x" "y" "X1" "X2" ...
# ..$ : NULL
Кадр данных стал символьной матрицей.Как это случилось?Хорошо, проверьте текст справки для метода транспонирования для фреймов данных: ?t.data.frame
:
Фрейм данных сначала приведен к матрице: см. as.matrix
.
OK, см. ?as.matrix
:
Метод для фреймов данных возвращает матрицу символов, если есть только атомарные столбцы и любой не (числовой / логический / сложный)столбец [...]
В то время как фрейм данных - это список, в котором каждый столбец может иметь класс другого , матрица - это просто вектор с измерениями, который может содержать только один класс.Таким образом, поскольку у вас есть хотя бы один символьный столбец, то есть столбец (не числовой / логический / сложный), ваш фрейм данных приводится к символьной матрице в результате t
транспонирования.Затем вы приводите матрицу к фрейму данных, где все столбцы являются символьными (или factor
, в зависимости от настроек stringsAsFactors
) - отметьте str(data.frame(d_t))
.
На втором шаге размерразличных объектов сравнивается.Начните с фрейма данных и его транспонирования, как было создано выше:
# original data frame
object.size(d)
# 2360 bytes
# transposed df - a character matrix
object.size(d_t)
# 3280 bytes
Транспонированный объект явно больше.Если мы увеличим число строк и количество числовых столбцов, чтобы лучше имитировать ваши данные, относительная разница будет еще больше:
nr <- 56202
nc <- 20
object.size(d)
# 9897712 bytes
object.size(d_t)
# 78299656 bytes
Поскольку количество элементов в исходном и транспонированном одинаководанные, размер (памяти) каждого отдельного элемента должен отличаться.Давайте проверим размер integer
, numeric
и character
векторов одинаковой длины.Во-первых, векторы с однозначными значениями и соответствующий вектор односимвольных элементов:
onedigit_int <- sample(1:9, 1e4, replace = TRUE)
onedigit_num <- as.numeric(onedigit_int)
onedigit_char <- as.character(onedigit_int)
object.size(onedigit_int)
# 40048 bytes
object.size(onedigit_num)
# 80048 bytes
object.size(onedigit_char)
# 80552 bytes
Для одиночных цифр / символов integer
векторов занимают 4 байта на элемент, а numeric
и character
векторов 8 байтов на элемент.Односимвольный вектор не требует больше памяти, чем числовой вектор.Означает ли это, что мы можем отвергнуть идею о том, что увеличение общего размера объясняется приведением большого числа числовых переменных к символу?Что ж, нам нужно проверить, что происходит с векторами с многозначными числами (которые у вас, похоже, есть) и соответствующими им векторами из многосимвольных строк:
multidigit_int <- sample(1:1e6, 1e4, replace = TRUE)
multidigit_num <- as.numeric(multidigit_int)
multidigit_char <- as.character(multidigit_int)
object.size(multidigit_int)
# 40048 bytes
object.size(multidigit_num)
# 80048 bytes
object.size(multidigit_char)
# 637360 bytes
Целочисленный вектор по-прежнему занимает 4 байта для каждого элементачисловой вектор по-прежнему занимает 8 байтов для каждого элемента.Тем не менее, размер каждого элемента в символьном векторе больше для больших строк.
Таким образом, транспонирование приводит ваш фрейм данных к символьной матрице, и размер каждого символьного элемента большечем соответствующий ему числовой элемент.
Транспонирование кадра данных со столбцами другого класса очень редко имеет смысл.И если все столбцы относятся к одного и того же класса, то мы также можем использовать матрицу с самого начала.
Подробнее о том, сколько памятииспользуется для хранения различных объектов в Advanced R by Hadley Wickham