Przycinanie ogromnego (3,5 GB) pliku csv do wczytania do R

Więc mam plik danych (oddzielony średnikami), który ma wiele szczegółów i niepełne wiersze(dostęp wiodący i SQL do dławika). Jest to zbiór danych na poziomie hrabstwa podzielony na segmenty, pod segmenty i pod segmenty (w sumie ~ 200 czynników) przez 40 lat. Krótko mówiąc, jest ogromny i nie zmieści się w pamięci, jeśli spróbuję go po prostu przeczytać.

Więc moje pytanie jest takie, biorąc pod uwagę, że chcę wszystkie powiaty, ale tylko jeden rok (i tylko najwyższy poziom segment... doprowadzając do około 100 000 rzędów w końcu), jaki byłby najlepszy sposób na wprowadzenie tego rollupa do R?

Obecnie próbuję wyciąć nieistotne lata z Pythonem, ominąć limit rozmiaru plików, czytając i operując na jednej linii na raz, ale wolałbym rozwiązanie tylko dla R (Pakiety CRAN OK). Czy istnieje podobny sposób odczytywania w plikach fragmentu na raz w R?

Wszelkie pomysły byłyby bardzo doceniam to.

Update:

    • musi użyć mojej maszyny, więc nie ma instancji EC2
    • Jak R-TYLKO jak to możliwe. Szybkość i zasoby nie są w tym przypadku problemem... pod warunkiem, że moja maszyna nie eksploduje...
    • Jak widać poniżej, dane zawierają typy mieszane, na których muszę działać później
  • dane
    • Dane są 3,5 GB, z około 8,5 mln wierszy i 17 kolumn
    • A kilka tysięcy wierszy (~2k) jest zniekształconych, tylko jedna kolumna zamiast 17
      • są one całkowicie nieistotne i można je usunąć
    • potrzebuję tylko ~100 000 wierszy z tego pliku (patrz poniżej)

Przykład danych:

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC  [Malformed row]
[8.5 Mill rows]

Chcę wyciąć kilka kolumn i wybrać dwa z 40 dostępnych lat (2009-2010 od 1980-2020), aby dane mogły zmieścić się w R:

County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]

Wyniki:

Po majstrowaniu przy wszystkich sugestie, uznałem, że najlepiej sprawdzą się lektury, sugerowane przez JD i Marka. Dałem Markowi czek, bo dał przykładową realizację.

Odtworzyłem nieco dostosowaną wersję implementacji Marka dla mojej ostatecznej odpowiedzi tutaj, używając strsplit i cat, aby zachować tylko kolumny, które chcę.

Należy również zauważyć, że jest todużo mniej wydajne niż Python... podobnie jak Python chomps przez plik 3.5 GB w 5 minut, podczas gdy R zajmuje około 60... ale jeśli wszystko ty have is R then this is the ticket.

## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
  line.split <- strsplit(line, ';')
  if (length(line.split[[1]]) > 1) {
    if (line.split[[1]][3] == '2009') {
        cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
    }
  }
  line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)

  • sqldf
    • to jest zdecydowanie to, co wykorzystam do tego typu problemu w przyszłości, jeśli dane będą dobrze uformowane. Jeśli jednak nie, to SQLite dławi się.
  • MapReduce
    • szczerze mówiąc, lekarze trochę mnie onieśmielili, więc nie próbowałem. Wyglądało na to, że wymaga również, aby obiekt był w pamięci, co pokonałoby punkt, jeśli tak było.
  • bigmemory
    • takie podejście jest ściśle powiązane z danymi, ale może obsługiwać tylko jeden typ na raz. W rezultacie, wszystkie moje wektory postaci spadła, gdy umieścić w dużym.stolik. Jeśli jednak muszę projektować duże zbiory danych na przyszłość, rozważyłbym użycie tylko liczb, aby utrzymać tę opcję przy życiu.
  • skan
    • Scan wydawał się mieć podobne problemy typu jak duża pamięć, ale z całą mechaniką linii odczytu. W krótko, tym razem nie pasowało do rachunku.
 87
Author: xiaodai, 2010-06-22

13 answers

Moja próba z readLines. Ten fragment kodu tworzy csv z zaznaczonymi latami.

file_in <- file("in.csv","r")
file_out <- file("out.csv","a")
x <- readLines(file_in, n=1)
writeLines(x, file_out) # copy headers

B <- 300000 # depends how large is one pack
while(length(x)) {
    ind <- grep("^[^;]*;[^;]*; 20(09|10)", x)
    if (length(ind)) writeLines(x[ind], file_out)
    x <- readLines(file_in, n=B)
}
close(file_in)
close(file_out)
 40
Author: Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-24 08:45:49

Nie jestem w tym ekspertem, ale możesz rozważyć wypróbowanie MapReduce , co w zasadzie oznaczałoby przyjęcie podejścia "dziel i rządź". R ma kilka opcji, w tym:

  1. mapReduce (pure R)
  2. RHIPE (który używa Hadoop ); Zobacz przykład 6.2.2 w dokumentacji dla przykładu podzestawów plików

Alternatywnie, r dostarcza kilka pakietów do radzenia sobie z dużymi danymi, które wykraczają poza pamięć (na dysk). Możesz prawdopodobnie załadować cały zbiór danych do obiektu bigmemory i wykonać redukcję całkowicie w obrębie R. Zobacz http://www.bigmemory.org / za zestaw narzędzi do tego.

 10
Author: Shane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 16:25:47

Czy istnieje podobny sposób odczytywania w plikach fragmentu na raz w R?

Tak. Funkcja readChar () będzie czytać w bloku znaków bez zakładania, że są zakończone znakiem null. Jeśli chcesz odczytać dane w wierszu na raz, możesz użyć readLines(). Jeśli czytasz blok lub linię, wykonujesz operację, a następnie zapisujesz dane, możesz uniknąć problemu z pamięcią. Chociaż jeśli masz ochotę odpalić dużą instancję pamięci na Amazon EC2 możesz wstać do 64GB pamięci RAM. To powinno pomieścić Twój plik i dużo miejsca na manipulowanie danymi.

Jeśli potrzebujesz większej prędkości, to rekomendacja Shane ' a, aby użyć Map Reduce, jest bardzo dobra. Jeśli jednak używasz dużej instancji pamięci w EC2, powinieneś przyjrzeć się pakietowi wielordzeniowemu, aby używać wszystkich rdzeni na komputerze.

Jeśli chcesz odczytać wiele GIGA rozdzielonych danych do R, powinieneś przynajmniej zapoznać się z pakietem sqldf, który pozwala importować bezpośrednio do sqldf z R, a następnie operować na danych z R. znalazłem sqldf jako jeden z najszybszych sposobów importowania gigs danych do R, jak wspomniano w to poprzednie pytanie .

 10
Author: JD Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:34

Jest zupełnie nowy pakiet o nazwie colbycol, który pozwala odczytywać tylko zmienne, które chcesz z ogromnych plików tekstowych:

Http://colbycol.r-forge.r-project.org/

Przekazuje wszelkie argumenty do przeczytania.tabelę, więc kombinacja powinna pozwolić ci dość mocno

 6
Author: Ari B. Friedman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-04 12:22:34

Pakiet ff jest przejrzystym sposobem radzenia sobie z ogromnymi plikami.

Możesz zobaczyć pakiet strona internetowai/lub prezentacja o nim.

Mam nadzieję, że to pomoże

 6
Author: Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-09 20:19:20

A co z użyciem readr i read_*_chunked rodzina?

Więc w Twoim przypadku:

Testfile.csv

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5
lol
Ada County;NC;2013;1;FIRE;Financial;Banks;82.5

Kod rzeczywisty

require(readr)
f <- function(x, pos) subset(x, Year %in% c(2009, 2010))
read_csv2_chunked("testfile.csv", DataFrameCallback$new(f), chunk_size = 1)

Odnosi się to f do każdego fragmentu, pamiętając nazwy col i łącząc filtrowane wyniki na końcu. Zobacz też ?callback który jest źródłem tego przykładu.

To daje:

# A tibble: 2 × 8
      County State  Year Quarter Segment `Sub-Segment` `Sub-Sub-Segment`   GDP
*      <chr> <chr> <int>   <int>   <chr>         <chr>             <chr> <dbl>
1 Ada County    NC  2009       4    FIRE     Financial             Banks   801
2 Ada County    NC  2010       1    FIRE     Financial             Banks   825

Możesz nawet zwiększyć chunk_size, ale w tym przykładzie są tylko 4 linie.

 6
Author: Rentrop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-02 09:50:58

Możesz zaimportować dane do bazy danych SQLite, a następnie użyć RSQLite, aby wybrać podzbiory.

 5
Author: Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 16:36:49

Czy udało Ci się zmyślić bigmemory ? Zobacz to i to .

 4
Author: George Dontas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 16:30:39

Być może możesz przeprowadzić migrację do MySQL lub PostgreSQL, aby zapobiec ograniczeniom MS Access.

Dość łatwo jest podłączyć R do tych systemów za pomocą złącza bazodanowego DBI (dostępnego na CRAN).

 3
Author: FloE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 16:36:42

Scan () ma zarówno argument nlines, jak i argument skip. Czy jest jakiś powód, dla którego możesz po prostu użyć tego, aby odczytać w kawałku linii czas, sprawdzając datę, aby sprawdzić, czy jest to właściwe? Jeśli plik wejściowy jest uporządkowany według daty, Możesz zapisać indeks, który informuje o tym, jakie powinny być linie skip i nlines, które przyspieszą proces w przyszłości.

 3
Author: frankc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-23 20:38:18

Te dni, 3.5 GB po prostu nie jest tak duża, mogę uzyskać dostęp do maszyny z 244GB RAM (r3. 8xlarge) na chmurze Amazon za $ 2.80 / godzinę. Ile godzin zajmie ci rozwiązanie problemu za pomocą rozwiązań typu big data? Ile jest wart twój czas? Tak, zajmie ci to godzinę lub dwie, aby dowiedzieć się, jak korzystać z AWS - ale możesz nauczyć się podstaw na darmowej warstwie, przesłać dane i odczytać pierwsze linie 10k do R, aby sprawdzić, czy działa, a następnie możesz odpalić dużą instancja pamięci jak r3. 8xlarge i przeczytaj to wszystko! Tylko moje 2C.

 2
Author: Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-17 11:07:59

Teraz, 2017, proponuję wybrać spark i sparkR.

  • Składnia może być napisana w prosty, raczej dplyr-podobny sposób

  • Całkiem dobrze pasuje do małej pamięci (małej w sensie 2017)

Jednak rozpoczęcie pracy może być onieśmielające...

 0
Author: Ott Toomet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 03:39:49

Chciałbym przejść do DB, a następnie zrobić kilka zapytań, aby wyodrębnić próbki, których potrzebujesz przez DBI

Proszę unikać importowania pliku csv 3,5 GB do SQLite. Albo przynajmniej sprawdź, czy twój ogromny db mieści się w granicach SQLite, http://www.sqlite.org/limits.html

Masz cholernie Duże DB. Wybrałbym MySQL, jeśli potrzebujesz szybkości. Ale bądź przygotowany na to, aby czekać wiele godzin na zakończenie importu. Chyba, że masz jakiś niekonwencjonalny sprzęt lub piszesz z przyszłość...

EC2 Amazona może być dobrym rozwiązaniem również do tworzenia instancji serwera z R i MySQL.

Moje dwa skromne grosze warte.

 -3
Author: Liborio Francesco Cannici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 21:14:05