R 在转置数据帧时,对象大小会大幅增加

R 在转置数据帧时,对象大小会大幅增加,r,dataframe,memory,transpose,R,Dataframe,Memory,Transpose,我有一个大约50000个RNA转录本的数据框,每行有10000个不同的样本。数据帧的大小为4.9GB 然后,我必须转置数据,以便稍后正确地将其子集: df首先,你要写: 然后我必须转置这个数据集,以便稍后正确地将其子集 老实说,我怀疑你必须这么做。因此,这可能是一个XY问题。尽管如此,我认为剖析这个问题可能会引起普遍的兴趣 对象大小的增加很可能是由于对象在转置前后的类别发生了变化,以及不同类别的对象具有不同大小的事实 我将用一些例子来说明这一点。我们从换班开始 创建一个玩具数据框,其结构类似于

我有一个大约50000个RNA转录本的数据框,每行有10000个不同的样本。数据帧的大小为4.9GB

然后,我必须转置数据,以便稍后正确地将其子集:

df首先,你要写:

然后我必须转置这个数据集,以便稍后正确地将其子集

老实说,我怀疑你必须这么做。因此,这可能是一个XY问题。尽管如此,我认为剖析这个问题可能会引起普遍的兴趣


对象大小的增加很可能是由于对象在转置前后的
类别
发生了变化,以及不同类别的对象具有不同大小的事实

我将用一些例子来说明这一点。我们从换班开始

创建一个玩具数据框,其结构类似于您的,有几个字符列和几个数字列:

# 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)
数据帧已成为字符矩阵。这是怎么发生的?好的,检查数据帧转置方法的帮助文本:
?t.data.frame

首先将数据帧强制为矩阵:请参见
as.matrix

好的,请参见
?as.matrix

如果只有原子列和任何非(数字/逻辑/复杂)列[…],则数据帧的方法将返回字符矩阵

数据帧是一个列表,其中每个列可以属于不同的类,而矩阵只是一个具有维度的向量,它只能包含一个类。因此,由于您至少有一个字符列,即非-(数字/逻辑/复杂)列,因此数据帧由于
t
transpose而强制为字符矩阵。然后将矩阵强制为数据帧,其中所有列都是字符(或
因子
,具体取决于
stringsafactors
设置)-检查
str(data.frame(dut))


在第二步中,比较不同对象的大小。从数据帧及其转置开始,如上所述:

# 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
对于单个数字/字符,
整数
矢量每个元素占用4个字节,
数字
字符
矢量每个元素占用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  

multi-digital\u int感谢您的回复!你是对的,问题出在对象类型上。事实上,当我整个下午都在争论数据并将其转换回数字和因子时,我自己确实设法缩小了大小,但你的解释帮助我理解了为什么这会产生如此大的差异。你说你不认为我首先需要转置它,但我这么做是因为我想合并到另一个文件中,以便根据组织类型进行子集。我知道如何子集的唯一方法是将样本按行排列,将基因按列排列,因此需要转置。嗨@PhilD谢谢你的反馈。关于你是否需要转置,在没有看到你的数据和对你试图表达的内容的更全面描述的情况下,我只能猜测(因此我的“可能”)。不过,如果你允许我猜测,听起来你可以考虑的另一种选择是把你的数据从宽变长。然后合并/子集。干杯
# 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
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
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