Mam bardzo duże tabele (30 milionów wierszy), które chciałbym załadować, ponieważ ramki danych w R. read.table()
mają wiele wygodnych funkcji, ale wygląda na to, że w implementacji jest dużo logiki, która spowolniłaby wszystko. W moim przypadku zakładam, że znam typy kolumn z wyprzedzeniem, tabela nie zawiera żadnych nagłówków kolumn ani nazw wierszy i nie ma żadnych znaków patologicznych, o które muszę się martwić.
Wiem, że czytanie w tabeli przy użyciu listy scan()
może być dość szybkie, np .:
datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))
Ale niektóre z moich prób przekształcenia tego w ramkę danych wydają się zmniejszać wydajność powyższego współczynnika 6:
df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))
Czy jest na to lepszy sposób? A może całkiem inne podejście do problemu?
feather
. Do odczytu danychfeather
jest znacznie szybszy niżfread
. Na przykład w właśnie załadowanym zestawie danych 4 GBread_feather
było około 4,5 razy szybsze niżfread
. Zapisywanie danychfwrite
jest jeszcze szybsze. blog.dominodatalab.com/the-r-data-io-shootoutfeather
Jest więc szybszy do czytania, ale zajmuje dużo więcej miejsca do przechowywania.feather
to dobra opcja. Jeśli zależy ci tylko na możliwości odczytu danych w języku R,rds
lepiej jest.Oto przykład, który korzysta
fread
zdata.table
1.8.7Przykłady pochodzą ze strony pomocy do
fread
, wraz z czasami na moim Windows XP Core 2 duet E8400.standardowy stół do odczytu
zoptymalizowany stół do odczytu
fread
sqldf
ff / ffdf
W podsumowaniu:
źródło
fread
. Próbowałem go odczytać za pomocą podstawowych funkcji R. Zajęło to około 15 godzin.readr
?fread
ma teraz prawdziwych konkurentów, może być przydatne dodanie punktów odniesienia dla zoptymalizowanegofread
użycia - określaniecolClasses
itp.Początkowo nie widziałem tego pytania i kilka dni później zadałem podobne pytanie. Mam zamiar usunąć moje poprzednie pytanie, ale pomyślałem, że dodam tutaj odpowiedź, aby wyjaśnić, jak to wykorzystałem
sqldf()
.Trwa dyskusja na temat najlepszego sposobu zaimportowania 2 GB lub więcej danych tekstowych do ramki danych R. Wczoraj napisałem wpis na blogu o
sqldf()
zaimportowaniu danych do SQLite jako obszaru przejściowego, a następnie wyssaniu go z SQLite do R. To działa bardzo dobrze dla mnie. Udało mi się pobrać 2 GB danych (3 kolumny, rzędy 40 mm) w <5 minut. Natomiastread.csv
polecenie działało całą noc i nigdy się nie zakończyło.Oto mój kod testowy:
Skonfiguruj dane testowe:
Zrestartowałem R przed uruchomieniem następującej procedury importowania:
Pozwoliłem, aby następująca linia działała całą noc, ale nigdy się nie zakończyła:
źródło
O dziwo, nikt przez lata nie udzielał odpowiedzi na dolną część pytania, mimo że jest to ważna -
data.frame
są to po prostu listy z odpowiednimi atrybutami, więc jeśli masz duże dane, których nie chcesz używaćas.data.frame
lub podobne do listy. Znacznie szybciej jest po prostu „przekształcić” listę w ramkę danych w miejscu:Nie powoduje to kopiowania danych, więc jest natychmiastowe (w przeciwieństwie do wszystkich innych metod). Zakłada się, że odpowiednio ustawiłeś już
names()
na liście.[Jeśli chodzi o ładowanie dużych danych do R - osobiście, zrzucam je kolumnami do plików binarnych i używam
readBin()
- jest to zdecydowanie najszybsza metoda (inna niż mapowanie) i jest ograniczona tylko prędkością dysku. Analiza plików ASCII jest z natury powolna (nawet w C) w porównaniu do danych binarnych.]źródło
tracmem
sugerujeattr<-
iclass<-
rób kopie wewnętrznie.bit::setattr
albodata.table::setattr
nie będzie.df=scan(...); names(df)=...; attr...; class...
- patrztracemem()
(testowane w R 2.15.2)To było wcześniej zadawane w R-Help , więc warto to sprawdzić.
Jedną z sugestii było użycie,
readChar()
a następnie manipulowanie ciągiem wyników za pomocąstrsplit()
isubstr()
. Widać, że logika związana z readChar jest znacznie mniejsza niż read.table.Nie wiem, czy pamięć jest tutaj problemem, ale możesz również rzucić okiem na pakiet HadoopStreaming . Ten wykorzystuje Hadoop , który stanowi ramy MapReduce przeznaczone do czynienia z dużymi zbiorami danych. W tym celu użyłbyś funkcji hsTableReader. To jest przykład (ale ma krzywą uczenia się do nauki Hadoop):
Podstawową ideą jest podzielenie importu danych na części. Możesz nawet posunąć się do tego, aby użyć jednej z równoległych struktur (np. Śniegu) i równolegle uruchomić import danych, dzieląc plik, ale najprawdopodobniej w przypadku dużych zestawów danych, które nie pomogą, ponieważ napotkasz ograniczenia pamięci, dlatego redukcja mapy jest lepszym podejściem.
źródło
Alternatywą jest użycie
vroom
pakietu. Teraz w CRAN.vroom
nie ładuje całego pliku, indeksuje lokalizację każdego rekordu i jest czytany później, gdy go użyjesz.Zobacz Wprowadzenie do vroom , Rozpocznij z vroom i testy porównawcze vroom .
Podstawowy przegląd jest taki, że początkowy odczyt dużego pliku będzie znacznie szybszy, a kolejne modyfikacje danych mogą być nieco wolniejsze. W zależności od tego, jakie jest twoje zastosowanie, może to być najlepsza opcja.
Zobacz uproszczony przykład z testów porównawczych vroom poniżej, najważniejsze elementy to super szybki czas odczytu, ale operacje nieco rozsiewające, takie jak agregacja itp.
źródło
Drobne dodatkowe punkty, o których warto wspomnieć. Jeśli masz bardzo duży plik, możesz w locie obliczyć liczbę wierszy (jeśli nie ma nagłówka), używając (gdzie
bedGraph
jest nazwa pliku w katalogu roboczym):Następnie można użyć, że albo w
read.csv
,read.table
...źródło
Często myślę, że dobrą praktyką jest przechowywanie większych baz danych w bazie danych (np. Postgres). Nie używam niczego większego niż (nrow * ncol) ncell = 10M, co jest dość małe; ale często stwierdzam, że chcę, aby R tworzył i przechowywał wykresy wymagające dużej ilości pamięci tylko podczas zapytania z wielu baz danych. W przyszłości laptopy o pojemności 32 GB znikną niektóre z tych problemów z pamięcią. Ale urok użycia bazy danych do przechowywania danych, a następnie użycia pamięci R do wynikowych wyników zapytań i wykresów nadal może być przydatny. Niektóre zalety to:
(1) Dane pozostają ładowane do bazy danych. Po prostu ponownie pgadmin łączy się z bazami danych, które chcesz po ponownym włączeniu laptopa.
(2) Prawdą jest, że R może wykonać znacznie więcej sprytnych operacji statystycznych i graficznych niż SQL. Ale myślę, że SQL jest lepiej zaprojektowany do wyszukiwania dużych ilości danych niż R.
źródło
Bardzo szybko czytam dane, używając nowego
arrow
pakietu. Wydaje się, że jest na dość wczesnym etapie.W szczególności używam parkietowego formatu kolumnowego. To konwertuje z powrotem na
data.frame
R, ale możesz uzyskać jeszcze głębsze przyspieszenia, jeśli tego nie zrobisz. Ten format jest wygodny, ponieważ można go również używać z języka Python.Mój główny przypadek użycia tego jest na dość ograniczonym serwerze RShiny. Z tych powodów wolę trzymać dane dołączone do aplikacji (tj. Poza SQL), a zatem wymagają małego rozmiaru pliku i szybkości.
Ten powiązany artykuł zawiera analizę porównawczą i dobry przegląd. Poniżej zacytowałem kilka interesujących punktów.
https://ursalabs.org/blog/2019-10-columnar-perf/
Rozmiar pliku
Czytaj prędkość
Niezależny test
Przeprowadziłem niezależne testy porównawcze na symulowanym zbiorze danych obejmującym 1 000 000 wierszy. Zasadniczo przetasowałem kilka rzeczy, aby spróbować zakwestionować kompresję. Dodałem również krótkie pole tekstowe z losowymi słowami i dwoma symulowanymi czynnikami.
Dane
Czytaj i pisz
Zapisywanie danych jest łatwe.
Odczytywanie danych jest również łatwe.
Przetestowałem czytanie tych danych w stosunku do kilku konkurencyjnych opcji i uzyskałem nieco inne wyniki niż w powyższym artykule, który jest oczekiwany.
Ten plik nie jest tak duży jak artykuł porównawczy, więc może to jest różnica.
Testy
as_data_frame = FALSE
)arrow
)feather
)Spostrzeżenia
W przypadku tego konkretnego pliku
fread
jest on naprawdę bardzo szybki. Podoba mi się mały rozmiar pliku z wysoce skompresowanegoparquet2
testu. Mogę poświęcić czas na pracę z rodzimym formatem danych, a nie zdata.frame
jeśli naprawdę potrzebuję przyspieszenia.Tutaj
fst
jest również doskonałym wyborem. Używałbym mocno skompresowanegofst
formatu lub wysoce skompresowanego, wparquet
zależności od tego, czy potrzebuję kompromisu prędkości lub rozmiaru pliku.źródło
Zamiast konwencjonalnej tabeli read.tab czuję, że fread jest szybszą funkcją. Określenie dodatkowych atrybutów, takich jak wybranie tylko wymaganych kolumn, określenie klas i łańcucha, ponieważ czynniki skracają czas importowania pliku.
źródło
Próbowałem już wszystkiego i [readr] [1] wykonał najlepszą robotę. Mam tylko 8 GB pamięci RAM
Pętla na 20 plików, każdy 5 GB, 7 kolumn:
źródło