将新数据附加到 R 中的现有数据框 (RDS)

Posted

技术标签:

【中文标题】将新数据附加到 R 中的现有数据框 (RDS)【英文标题】:Append new data to an existing dataframe (RDS) in R 【发布时间】:2012-12-14 02:37:30 【问题描述】:

我有一个 Rscript,它以平面文件的形式读取恒定的数据流。另一个脚本获取这个平面文件,进行一些解析和处理,然后将结果保存为 RDS 格式的 data.frame。然后它休眠,并重复该过程。

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(我知道字面上没有)这样的东西可以实现我想要的——迭代更新单个数据框——保存到文件中——使用追加而不是完全替换?

【问题讨论】:

好吧,我认为你一开始就做坏事。您正在覆盖以前的数据,从而有效地删除了以前的版本。也就是说,为什么不使用write.table 以文本形式(例如CSV)保存您的数据,这确实允许附加到现有文档? 我实际上是用 rbind 到最新记录的先前数据的副本覆盖先前的数据。希望我的第二块展示了这个过程——读入旧的,追加新的,用旧的+新的覆盖旧的。我现在看到了 write.table 附加选项。我一直远离非原生格式,因为我认为它会增加处理开销。但我可能会接受在这一步中牺牲一点效率以获得更好的稳定性。 我想知道是否可以使用 ?serialize 的一些魔法来创建附加函数。 【参考方案1】:

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

如果您想坚持使用单个文件但尽量减少从 RDS 文件中读取不一致数据的风险,您可以将其读入,执行附加操作,然后将其写入临时文件并重命名临时文件完成后改成原来的名字。那么至少您的风险期不取决于文件的大小。我不熟悉将文件重命名为现有名称时各种文件系统保证什么样的原子性,但它可能比 saveRDS 所花费的时间更好。

【讨论】:

有趣的想法。读入所有 RDS 文件需要花点功夫;然后进入操作系统进行删除/重命名。聪明,但超出了我的耐心;)。 您可以编写一个函数来替代saveRDS,它写入临时文件并重命名。【参考方案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)

【讨论】:

非常感谢。看起来它可以在同一个脚本中工作。如果另一个脚本(即另一个进程)同时访问同一个 RDS,这是否有助于保护它?恐怕我对并发的唯一经验是数据库,而不是文件。 @Brandon-Bertselsen 工作! #pass1 con &lt;- file("H:/Documents/tweet.df.rds") while(isOpen(con)) Sys.sleep(2) open(con, "wb") saveRDS(tmp.df, con) close(con, type="rw") #Pass N con &lt;- file("H:/Documents/tweet.df.rds") while(isOpen(con)) Sys.sleep(2) open(con, "rb") df2 &lt;- readRDS(con) close(con, type="rw") tmp.df2 &lt;- rbind(df2, tmp.df) con &lt;- file("H:/Documents/tweet.df.rds") while(isOpen(con)) Sys.sleep(2) open(con, "wb") saveRDS(tmp.df2, con) close(con, type="rw") 可能在打开/关闭时有些矫枉过正,但我​​可以接受。

以上是关于将新数据附加到 R 中的现有数据框 (RDS)的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 Python 中的索引时间序列条件将新数据集附加到现有数据集

无法在不覆盖的情况下将 R 数据框附加到现有 Excel 中

迭代获取数据框列的最大值,加一并重复 r 中的所有行

在 UDF 之后将新列附加到现有 PySpark 数据帧

有没有办法在不使用 XDocument 的情况下将新的 xml 数据附加到 xml 文件中的现有 xml?

如何使用 pymongo 将新的值数组附加到 mongodb 中的现有数组文档?