R数据表按组的高效复制
我在尝试使用data.table和rep按组复制某些数据时遇到了一些内存分配问题 以下是一些示例数据:R数据表按组的高效复制,r,data.table,replicate,R,Data.table,Replicate,我在尝试使用data.table和rep按组复制某些数据时遇到了一些内存分配问题 以下是一些示例数据: ob1 <- as.data.frame(cbind(c(1999),c("THE","BLACK","DOG","JUMPED","OVER","RED","FENCE"),c(4)),stringsAsFactors=FALSE) ob2 <- as.data.frame(cbind(c(2000),c("I","WALKED","THE","BLACK","DOG"),c(3
ob1 <- as.data.frame(cbind(c(1999),c("THE","BLACK","DOG","JUMPED","OVER","RED","FENCE"),c(4)),stringsAsFactors=FALSE)
ob2 <- as.data.frame(cbind(c(2000),c("I","WALKED","THE","BLACK","DOG"),c(3)),stringsAsFactors=FALSE)
ob3 <- as.data.frame(cbind(c(2001),c("SHE","PAINTED","THE","RED","FENCE"),c(1)),stringsAsFactors=FALSE)
ob4 <- as.data.frame(cbind(c(2002),c("THE","YELLOW","HOUSE","HAS","BLACK","DOG","AND","RED","FENCE"),c(2)),stringsAsFactors=FALSE)
sample_data <- rbind(ob1,ob2,ob3,ob4)
colnames(sample_data) <- c("yr","token","multiple")
我想做的是按照当前的顺序,每年按倍数复制代币
以下代码有效,并给出了我想要的答案:
good_solution1 <- ddply(sample_data, "yr", function(x) data.frame(rep(x[,2],x[1,3])))
good_solution2 <- data.table(sample_data)[, rep(token,unique(multiple)),by = "yr"]
问题是,当我将其扩展到40mm+行时,两种可能的解决方案都会出现内存问题
如果我的理解是正确的,这些解决方案本质上是在做一个rbind,它每次都分配资源
有谁有更好的解决方案吗
我查看了set for data.table,但遇到了问题,因为我想在每次复制时保持令牌的顺序相同。一种方法是:
require(data.table)
dt <- data.table(sample_data)
# multiple seems to be a character, convert to numeric
dt[, multiple := as.numeric(multiple)]
setkey(dt, "multiple")
dt[J(rep(unique(multiple), unique(multiple))), allow.cartesian=TRUE]
但正如里卡多所说,如果你的内存不足,这可能并不重要。因此,在这种情况下,必须在速度和内存之间进行权衡。我想验证的是这两种方法中使用的峰值内存,以确定使用Join是否更好。一种方法是:
require(data.table)
dt <- data.table(sample_data)
# multiple seems to be a character, convert to numeric
dt[, multiple := as.numeric(multiple)]
setkey(dt, "multiple")
dt[J(rep(unique(multiple), unique(multiple))), allow.cartesian=TRUE]
但正如里卡多所说,如果你的内存不足,这可能并不重要。因此,在这种情况下,必须在速度和内存之间进行权衡。我想验证的是这两种方法中使用的峰值内存,确定使用Join是否更好。您可以尝试先为所有行分配内存,然后迭代填充它们。 例如:
您可以尝试先为所有行分配内存,然后迭代填充它们。 例如:
谢谢是的,角色问题只是我在创建示例数据时太笨了。你认为这种方法会占用更少的内存吗?我还没有为我的大样本实现它,但我注意到它也使用了replicate。你的解和我的好解有什么不同?它将为J中的每个值子集,并继续连接。所以,如果你有10个ID,每个ID有100行,并且是4的倍数,那么你会得到10*100*4=4000行,每个子集有100行。我怀疑Ricardo的解决方案可能是你在再次阅读你的问题后给出的答案。我只是在一个相对较大的数据上对这两种方法进行基准测试,但不会太大,以至于您意外地耗尽内存并使您的R会话崩溃,但足够清晰,可以区分最快的方法+内存谨慎的方法。+1处理银色数据。表标签:-对于帮助我学习anks的伟大解释!是的,角色问题只是我在创建示例数据时太笨了。你认为这种方法会占用更少的内存吗?我还没有为我的大样本实现它,但我注意到它也使用了replicate。你的解和我的好解有什么不同?它将为J中的每个值子集,并继续连接。所以,如果你有10个ID,每个ID有100行,并且是4的倍数,那么你会得到10*100*4=4000行,每个子集有100行。我怀疑Ricardo的解决方案可能是你在再次阅读你的问题后给出的答案。我只是在一个相对较大的数据上对这两种方法进行基准测试,但不会太大,以至于您意外地耗尽内存并导致R会话崩溃,但足够清晰,可以区分最快的方法+内存谨慎的方法。+1处理银色数据。表标签:-对于帮助我学习Ricardo的伟大解释,这是字符,因为他使用cbind和as.data.frame来创建数据。和cbind。创建一个矩阵,然后用as.data.frame环绕该矩阵。由于cbind没有数据帧输入,所以它是一个矩阵,所以每个值都转换为字符。谢谢Ricardo和Arun。里卡多,你的代码中有tokenRep和tokenRep,这是最后的答案和额外的一列。@RicardoSaporta,你的第一个分配步骤就是:newDT@Arun,真的!这是相当快和干净的一点。编辑我的答案以反映,谢谢!里卡多,这是角色,因为他使用cbind和as.data.frame创建数据。和cbind。创建一个矩阵,然后用as.data.frame环绕该矩阵。由于cbind没有数据帧输入,所以它是一个矩阵,所以每个值都转换为字符。谢谢Ricardo和Arun。里卡多,你的代码中有tokenRep和tokenRep,这是最后的答案和额外的一列。@RicardoSaporta,你的第一个分配步骤就是:newDT@Arun,真的!这是相当快和干净的一点。编辑我的答案以反映,谢谢!从版本1.9.2开始。2014年2月27日,在CRAN上,data.table获得了一个新的函数setDT,该函数获取一个列表或data.frame,并通过引用data.table更改其类型,而无需任何副本。因此,setDTsample_数据而不是data.tablesample_数据可能有助于节省内存。2014年2月27日,在CRAN上,data.table获得了一个新的函数setDT,该函数获取一个列表或data.frame,并通过引用data.table更改其类型,而无需任何副本。因此,setDTsample_数据而不是data.tablesample_数据可能有助于节省内存。
# make sure `sample_data$multiple` is an integer
sample_data$multiple <- as.integer(sample_data$multiple)
# create data.table
S <- data.table(sample_data, key='yr')
# optionally, drop original data.frame if not needed
rm(sample_data)
## Allocate the memory first
newDT <- data.table(yr = rep(sample_data$yr, sample_data$multiple), key="yr")
newDT[, tokenReps := as.character(NA)]
# Add the rep'd tokens into newDT, using recycling
newDT[, tokenReps := S[.(y)][, token], by=list(y=yr)]
S[, list(rows=length(token) * unique(multiple)), by=yr]