Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R数据表按组的高效复制_R_Data.table_Replicate - Fatal编程技术网

R数据表按组的高效复制

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

我在尝试使用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)),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]