在R中向现有的数据框(RDS)追加新数据

7

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

我认为你一开始就做错了。你正在覆盖以前的数据,从而有效地删除以前的版本。话虽如此,为什么不使用文本形式(例如CSV)保存数据,并使用write.table进行追加到现有文档呢? - Carl Witthoft
我实际上是用前一份数据的副本覆盖了先前的数据,将其与最新记录合并。希望我的第二个代码块展示了这个过程-读取旧数据,追加新数据,用旧数据+新数据覆盖旧数据。 我现在看到了write.table的追加选项。我一直避免使用非本地格式,因为我认为它会增加处理开销。但是我可能可以在这一步中牺牲一点效率来换取更好的稳定性。 - Amw 5G
我在想是否可以利用“?serialize”实现创建追加函数的魔法。 - Brandon Bertelsen
2个回答

5

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

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,这是否有助于保护它?我担心我的并发经验仅限于数据库,而不是文件。 - Amw 5G
工作了! `#pass1 con <- 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 <- file("H:/Documents/tweet.df.rds") while(isOpen(con)) { Sys.sleep(2) } open(con, "rb") df2 <- readRDS(con) close(con, type="rw") tmp.df2 <- rbind(df2, tmp.df)con <- file("H:/Documents/tweet.df.rds") while(isOpen(con)) { Sys.sleep(2) } open(con, "wb") saveRDS(tmp.df2, con) close(con, type="rw")` 也许在打开/关闭方面有些过度,但我可以接受。 - Amw 5G

1

在目录中使用一系列编号的RDS文件而不是单个RDS文件是否存在问题?我认为如果要将数据框附加到RDS文件中,则无法避免重写整个文件,因为数据框只是列的列表,因此它们被逐列序列化,因此仅最后一列接近文件末尾。

如果您想坚持使用单个文件但又最小化从RDS文件读取不一致数据的风险,可以将其读入,执行附加操作,然后将其写入临时文件并在完成后将临时文件重命名为原始名称。然后,至少您的风险期不取决于文件大小。我不熟悉在将文件重命名为现有名称时各种文件系统保证的原子性,但这可能比saveRDS所需的时间更好。


有趣的想法。需要一些技巧才能读取所有的RDS文件;然后再深入操作系统进行拖放/重命名。聪明,但超出了我的耐心 ;)。 - Amw 5G
你可以编写一个函数,作为 saveRDS 的即插即用替代品,将数据写入临时文件并重命名。 - Ryan C. Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接