2012-12-28 10 views
5

Mam Rscript, który czyta w stałym strumieniu danych w postaci pliku płaskiego. Inny skrypt odbiera ten plik płaski, wykonuje pewne przetwarzanie i przetwarzanie, a następnie zapisuje wynik jako dane.frame w formacie RDS. Następnie śpi i powtarza proces.Dołącz nowe dane do istniejącej ramki danych (RDS) w R

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

Na drugim ... n-tej iteracji, mam kod przetwarzać tylko nowe wiersze dodane do pliku płaskiego od poprzedniej iteracji. Jednakże, aby dołączyć linie delta do stałej ramki danych, muszę ją wczytać, dołączyć, a następnie zapisać z powrotem, zastępując oryginał.

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 

Podejście to jest ryzykowne, bo gdy RDS jest otwarty dla odczytu/zapisu, kolejny proces chcąc dotknąć ten plik musi czekać. Gdy plik podstawowy staje się większy, ryzyko wzrasta.

Czy istnieje coś takiego jak appendRDS (wiem dosłownie, że nie ma), że można osiągnąć to, co chcę - iteracyjne aktualizowanie pojedynczej ramki danych - zapisanej w pliku - która używa raczej zamiast do uzupełnienia?

+0

Cóż, myślę, że robisz coś złego w pierwszej kolejności. Nadpisujesz swoje poprzednie dane, tym samym skutecznie usuwając poprzednie wersje. To powiedziawszy, dlaczego nie zapisać danych w formie tekstowej (CSV, np.) Za pomocą 'write.table', co pozwala na dołączanie do istniejących dokumentów? –

+0

Naprawdę nadpisuję poprzednie dane kopią poprzednich danych, do ostatnich rekordów. Mam nadzieję, że mój drugi blok pokazuje, że proces czyta się w starym, dodaje nowe, nadpisuje stare ze starym + nowym. Teraz widzę opcję writeend.table. Trzymałem się z dala od formatu natywnego, ponieważ uznałem, że zwiększy to obciążenie przetwarzania. Ale mogę być w porządku, jeśli w tym kroku wymieniłem trochę nieefektywności na lepszą stabilność. –

+0

Zastanawiam się, czy można użyć jakiejś magii z? Serializować, aby utworzyć funkcję dopisywania. –

Odpowiedz

2

Myślę, że możesz zabezpieczyć swój proces, używając połączeń, otwierając i zamykając go, zanim przejmie następny proces.

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

Aktualizacja:

Można sprawdzić, czy połączenie do pliku jest otwarta i poinformować go czekać na trochę, jeśli masz problemy z współbieżności.

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

Dziękuję uprzejmie. Wygląda na to, że działałoby w tym samym skrypcie. Czy pomogłoby to w ochronie, gdyby inny skrypt (tj. Inny proces) uzyskiwał dostęp do tego samego systemu RDS w tym samym czasie? Obawiam się, że moje jedyne doświadczenie związane ze współbieżnością to bazy danych, a nie pliki. –

+0

@ Brandon-Bertselsen Pracuje! '# pass1 con <- pliku ("H: /Documents/tweet.df.rds") \t while (ISOpen (Con)) { \t \t Sys.sleep (2) \t} \t otwarte (Con "WB") \t saveRDS (tmp.df cON) \t blisko (con type = "RW") #Pass N con <- pliku ("H: /Documents/tweet.df.rds") \t while (ISOpen (con)) { \t \t Sys.sleep (2) \t} \t otwarte (Con "rb") \t df2 <- readRDS (Con) \t blisko (Con type = "RW") \t tmp.df2 <- rbind (df2, tmp.df) \t \t con <- pliku ("H: /Documents/tweet.df.rds") \t while (ISOpen (con)) { \t \t Sys.sleep (2) \t} \t otwarte (con "WB") \t saveRDS (tmp.df2, con) \t close (con, type = "rw") ' Może trochę przesady w open/zamknięcia, ale jestem z tym w porządku. –

1

Czy jest coś złego w korzystaniu z serii ponumerowanych plików RDS w katalogu zamiast pojedynczego pliku RDS? Nie sądzę, że istnieje możliwość dołączenia do ramki danych pliku RDS bez przepisywania całego pliku, ponieważ ramki danych są po prostu listami kolumn, więc przypuszczalnie są one serializowane jedną kolumną na raz, więc tylko ostatnia kolumna kończy się blisko końca pliku.

Jeśli chcesz trzymać się pojedynczego pliku, ale zminimalizować ryzyko odczytania niespójnych danych z pliku RDS, możesz go odczytać, wykonać operację dołączenia, a następnie zapisać w pliku tymczasowym i zmienić jego nazwę plik do oryginalnej nazwy po zakończeniu. Wtedy przynajmniej twój okres ryzyka nie zależy od wielkości pliku. Nie jestem zaznajomiony z tym, jaki rodzaj atomowości jest gwarantowany przez różne systemy plików podczas zmiany nazwy pliku na istniejącą nazwę, ale prawdopodobnie jest lepszy niż czas potrzebny na zapisanie.

+0

Interesujący pomysł. Wystarczyłoby trochę kowalstwa, aby wszystkie pliki RDS były czytane; a następnie sięgając do systemu operacyjnego, aby wykonać zrzut/zmienić nazwę. Sprytnie, ale poza moją cierpliwością;). –

+0

Możesz napisać funkcję, która działa jako zamiennik dla 'saveRDS', który zapisuje do pliku tymczasowego i zmienia nazwę. –

Powiązane problemy