Phi*_*l D 3 memory transpose r dataframe
我有一个ca.的数据框架.成排50,000个RNA转录本,列中有10,000个不同的样本.数据框的大小为4.9GB.
然后,我必须转置数据,以便以后正确地对其进行子集化:
df <- data.frame(t(df))
转置后,对象大小已经膨胀到70GB.为什么会这样?转置数据真的会改变文件大小吗?
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 ...
Run Code Online (Sandbox Code Playgroud)
首先,你写道:
然后,我必须转置此数据集,以便以后正确地对其进行子集化,
说实话,我怀疑你必须这样做.因此,这可能是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)
Run Code Online (Sandbox Code Playgroud)
转置它:
d_t <- t(d)
Run Code Online (Sandbox Code Playgroud)
检查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
Run Code Online (Sandbox Code Playgroud)
数据框已成为字符矩阵.这怎么发生的?那么,检查数据框的转置方法的帮助文本?t.data.frame:
首先将数据帧强制转换为矩阵:参见
as.matrix.
好的,请看?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
Run Code Online (Sandbox Code Playgroud)
转置的对象明显更大.如果我们增加行数和数字列数以更好地模拟数据,则相对差异甚至更大:
nr <- 56202
nc <- 20
object.size(d)
# 9897712 bytes
object.size(d_t)
# 78299656 bytes
Run Code Online (Sandbox Code Playgroud)
由于原始数据和转置数据中的元素数量相同,因此每个元素的(存储器)大小必须不同.让我们来看看的大小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
Run Code Online (Sandbox Code Playgroud)
对于单数字/字符,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
Run Code Online (Sandbox Code Playgroud)
整数向量仍然占用每个元素4个字节,数字向量仍然占用每个元素8个字节.然而,在字符向量每个元素的大小是较大的较大的字符串.
因此,转置将您的数据帧强制转换为字符矩阵,并且每个字符元素的大小大于其对应的数字元素.
使用不同类别的列来转置数据框很少是明智的.如果所有列都是同一类,那么我们也可以从一开始就使用矩阵.
阅读更多关于Hadley Wickham在Advanced R中使用多少内存来存储不同对象的信息