2012-12-28 117 views
5

我有一个Rscript以平面文件的形式读取恒定数据流。另一个脚本拾取这个平面文件,进行一些解析和处理,然后将结果保存为RDS格式的data.frame。它然后睡觉,并重复这个过程。将新数据追加到R中的现有数据帧(RDS)

saveRDS(tmp.df, file="H:/Documents/tweet.df.rds") #saving the data.frame 

在第二次...第n次迭代中,我只有代码处理自上次迭代以来添加到平面文件的新行。但是,为了将增量行附加到永久数据框中,我必须将其读入,追加,然后将其保存出来,覆盖原始数据。

df2 <- readRDS("H:/Documents/tweet.df.rds") #read in permanent      
tmp.df2 <- rbind(df2, tmp.df) #append new to existing 
saveRDS(tmp.df2, file="H:/Documents/tweet.df.rds") #save it 
rm(df2) #housecleaning 
rm(tmp.df2) #housecleaning 

这种做法是有风险的,因为每当RDS为您开放,读/写,另一个想触摸到了文件的过程必须等待。随着基础文件变大,风险增加。

是否有像appendRDS(我知道字面上没有)可以实现我想要的 - 迭代更新单个数据帧 - 保存到文件 - 使用附加而不是完全替换?

+0

嗯,我想你首先做的是坏事。您将覆盖以前的数据,从而有效地删除以前的版本。这就是说,为什么不直接用'write.table'将文本保存为文本格式(例如CSV),这允许附加到现有文档? –

+0

我实际上用先前数据的拷贝覆盖了以前的数据到最新的记录。希望我的第二部分内容显示这个过程 - 旧的读取,追加新的旧的旧的+新的旧的。 我现在看到write.table附加选项。我已经远离了非本地格式,因为我认为这会增加处理开销。不过,我可能会为了更好的稳定性而采取一些低效率的措施。 –

+0

我不知道是否有一些带有?serialize的魔法可以用来创建追加函数。 –

回答

2

我认为你可以通过使用连接来保护你的进程,在下一个进程接管之前打开和关闭它。

con <- file("tmp.rds") 
open(con) 
df <- readRDS(con) 
df.new <- rbind(df,df) 
saveRDS(df.new, con) 
close(con) 

更新:

您可以测试到文件的连接是开放的,并告诉它等待了一下,如果你遇到与并发问题。

while(is.Open(con)) { # untested but something of this nature should work 
sys.Sleep(2) 
} 
+0

谢谢。看起来它可以在同一个脚本中工作。如果另一个脚本(即另一个进程)同时访问同一个RDS,会有助于保护它吗?恐怕我唯一的并发经验是数据库,而不是文件。 –

+0

@ Brandon-Bertselsen 工作! '#PASS1 CON < - 文件( “H:/Documents/tweet.df.rds”) \t而(ISOPEN(CON)){ \t \t Sys.sleep(2) \t} \t打开(CON “WB”) \t saveRDS(tmp.df,CON) \t接近(CON,类型= “RW”) #Passñ CON < - 文件( “H:/Documents/tweet.df.rds”) \t而(ISOPEN(CON)){ \t \t Sys.sleep(2) \t} \t开放(CON, “RB”) \t DF2 < - readRDS(CON) \t接近(CON,类型= “RW”) \t tmp.df2 < - rbind(DF2,tmp.df) \t \t CON < - 文件( “H:/Documents/tweet.df.rds”) \t而(ISOPEN(CON)){ \t \t Sys.sleep(2) \t} \t开放(CON “WB”) \t saveRDS(tmp.df2,con) \t close(con,type =“rw”)' 也许在打开/关闭中有些矫枉过正,但我确定。 –

1

在目录中使用一系列编号的RDS文件而不是单个RDS文件有什么问题吗?我认为不可能在不重写整个文件的情况下将RDS文件附加到数据帧上,因为数据帧仅仅是列的列表,所以推测它们一次只能串行化一列,所以只有最后一列结束靠近文件的末尾。

如果您想坚持使用单个文件,但是最大限度地减少从RDS文件中读取不一致数据的风险,可以将其读入,执行附加操作,然后将其写入临时文件并重命名临时文件文件完成后恢复为原始名称。那么至少你的风险期不依赖于文件的大小。我不清楚在将文件重命名为现有名称时各种文件系统保证了什么样的原子性,但它可能比saveRDS花费的时间要好。

+0

有趣的想法。要读取所有RDS文件需要一点点锻炼;然后进入操作系统进行删除/重命名。聪明,但超出我的耐心;)。 –

+0

您可以编写一个函数作为'saveRDS'的插入替代品,写入临时文件并重命名。 –