Размер объекта значительно увеличивается при перемещении фрейма данных - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть кадр данных ок.50 000 РНК-транскриптов в строках, с 10 000 различных образцов в столбцах.Размер фрейма данных составляет 4,9 ГБ.

Затем мне нужно транспонировать данные, чтобы впоследствии правильно их поднастроить:

df <- data.frame(t(df))

После транспонированияразмер объекта увеличился до 70 ГБ.Почему это происходит?Должно ли транспонирование данных действительно так сильно изменять размер файла?

str() из первых 20 столбцов:

str(df[1:20])
Classes 'tbl_df', 'tbl' and 'data.frame':   56202 obs. of  20 variables:
 $ X1                      : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Name                    : chr  "ENSG00000223972.4" "ENSG00000227232.4" "ENSG00000243485.2" "ENSG00000237613.2" ...
 $ Description             : chr  "DDX11L1" "WASH7P" "MIR1302-11" "FAM138A" ...
 $ GTEX-1117F-0226-SM-5GZZ7: num  0.1082 21.4 0.1602 0.0505 0 ...
 $ GTEX-111CU-1826-SM-5GZYN: num  0.1158 11.03 0.0643 0 0 ...
 $ GTEX-111FC-0226-SM-5N9B8: num  0.021 16.75 0.0467 0.0295 0 ...
 $ GTEX-111VG-2326-SM-5N9BK: num  0.0233 8.172 0 0.0326 0 ...
 $ GTEX-111YS-2426-SM-5GZZQ: num  0 7.658 0.0586 0 0 ...
 $ GTEX-1122O-2026-SM-5NQ91: num  0.0464 9.372 0 0 0 ...
 $ GTEX-1128S-2126-SM-5H12U: num  0.0308 10.08 0.1367 0.0861 0.1108 ...
 $ GTEX-113IC-0226-SM-5HL5C: num  0.0936 13.56 0.2079 0.131 0.0562 ...
 $ GTEX-117YX-2226-SM-5EGJJ: num  0.121 9.889 0.0537 0.0677 0 ...
 $ GTEX-11DXW-0326-SM-5H11W: num  0.0286 9.121 0.0635 0 0 ...
 $ GTEX-11DXX-2326-SM-5Q5A2: num  0 6.698 0.0508 0.032 0 ...
 $ GTEX-11DZ1-0226-SM-5A5KF: num  0.0237 9.835 0 0.0664 0 ...
 $ GTEX-11EI6-0226-SM-5EQ64: num  0.0802 13.1 0 0 0 ...
 $ GTEX-11EM3-2326-SM-5H12B: num  0.0223 8.904 0.0496 0.0625 0.0402 ...
 $ GTEX-11EMC-2826-SM-5PNY6: num  0.0189 16.59 0 0.0265 0.034 ...
 $ GTEX-11EQ8-0226-SM-5EQ5G: num  0.0931 15.1 0.0689 0.0869 0 ...
 $ GTEX-11EQ9-2526-SM-5HL66: num  0.0777 9.838 0 0 0 ...

1 Ответ

0 голосов
/ 21 ноября 2018

Во-первых, вы пишете, что:

Затем мне нужно транспонировать этот набор данных для правильной подгруппы позже,

Если честно, я сомневаюсь, что у вас естьк.Таким образом, это может быть 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...