2013-03-20 8 views
16

Tytuł jest tutaj całkiem zrozumiały, ale opiszę to w następujący sposób. Niektóre z moich obecnych technik w atakowaniu tego problemu są oparte na rozwiązaniach przedstawionych w pytaniu this. Jednak stoję w obliczu wielu wyzwań i ograniczeń, więc zastanawiałem się, czy ktoś mógłby spróbować podjąć się tego problemu. Próbuję dowiedzieć się problem za pomocą pakietu bigmemory, ale mam problemy.Odczytywanie 40 GB pliku CSV na język R przy użyciu bigmemory

Obecne ograniczenia:

  • Korzystanie z serwera Linux z 16 GB pamięci RAM
  • Rozmiar 40 GB CSV
  • nr rzędów: 67.194.126.114

wyzwań

  • Konieczność losowego próbkowania mniejszych zestawów danych (5-10 milionów wierszy) z pliku big.matrix lub równoważnej struktury danych.
  • Konieczność usunięcia dowolnego wiersza z pojedynczą instancją o wartości NULL podczas analizowania w strukturze big.matrix lub równoważnej.

Do tej pory wyniki nie są dobre. Najwyraźniej coś mi się nie podoba, a może po prostu nie rozumiem wystarczająco dobrze. Pomyślałem, że zapytam, czy ktoś użył

Jakieś wskazówki, porady na temat linii ataku itp.? Czy powinienem zmienić coś innego? Przepraszam, jeśli to pytanie jest bardzo podobne do poprzedniego, ale według mnie skala danych była około 20 razy większa niż w poprzednich pytaniach. Dzięki !

+1

Co z przykładową zawartością pliku? –

+0

Gdzie dokładnie zawodzisz? Jakie dane znajdują się w pliku .csv - czy wszystkie są "podwójne", "int" lub w inny sposób? W jaki sposób są reprezentowane wpisy "NULL" w pliku? Czy istnieją nazwy wierszy/kolumn? I co próbowaliście? Biorąc pod uwagę .csv odpowiedniej struktury, 'read.big.matrix' powinien cię tam zabrać. –

+0

Więcej informacji byłoby dobrze, ale dlaczego nie zaimportować go do SQL, zrobić tam jakieś przygotowanie, a następnie załadować do R? –

Odpowiedz

18

Nie wiem o bigmemory, ale aby sprostać Twoim wyzwaniom, nie musisz czytać pliku. Po prostu przeprowadź kilka bitów/awk/sed/python/dowolne przetwarzanie, aby wykonać pożądane kroki, np. out NULL linii i losowo wybierz N linii, a następnie odczytać, że w.

Oto przykład przy użyciu awk (przy założeniu, że chcesz 100 losowych linii z pliku, który ma 1M linii).

read.csv(pipe('awk -F, \'BEGIN{srand(); m = 100; length = 1000000;} 
         !/NULL/{if (rand() < m/(length - NR + 1)) { 
           print; m--; 
           if (m == 0) exit; 
           }}\' filename' 
     )) -> df 

To nie było dla mnie oczywiste, co masz na myśli przez NULL, więc użyłem dosłowne rozumienie tego, ale to powinno być łatwe do zmodyfikować go do swoich potrzeb.

+1

To jest właściwie bardzo dobra odpowiedź, a kiedyś rozwiązałem mój problem, wprowadzając bardzo podobne rozwiązanie. Dziękuję za tę odpowiedź. Przyjmę to. – Shion

11

To jest czyste rozwiązanie problemu pobierania próbki z dużego pliku tekstowego; ma dodatkową zaletę losowego losowania próbki dokładnie n. Nie jest to zbyt mało wydajne, chociaż linie są przetwarzane na wektory znaków i jest to stosunkowo powolne.

Zaczynamy od podpisu funkcji, gdzie podajemy nazwę pliku, rozmiar próbki, którą chcemy narysować, nasienie generatora liczb losowych (abyśmy mogli odtworzyć naszą losową próbkę!), Wskazanie, czy istnieje wiersz nagłówka, a następnie funkcję „Czytelnik”, które będziemy używać do analizowania próbki do obiektu widzianego przez R, w tym dodatkowych argumentów ... że funkcja czytelnik może potrzebować

fsample <- 
    function(fname, n, seed, header=FALSE, ..., reader=read.csv) 
{ 

nasiona funkcji generatora liczb losowych, otwiera połączenie i odczytuje w (opcjonalnym) header linii

set.seed(seed) 
    con <- file(fname, open="r") 
    hdr <- if (header) { 
     readLines(con, 1L) 
    } else character() 

następnym krokiem jest, aby przeczytać w fragmencie n linii, inicjowanie licznik całkowitej liczby linie widoczne

buf <- readLines(con, n) 
    n_tot <- length(buf) 

dalej do odczytania w kawałkach z n liniami zatrzymania, gdy nie ma dodatkowo wejście

repeat { 
     txt <- readLines(con, n) 
     if ((n_txt <- length(txt)) == 0L) 
      break 

Dla każdego klocka, rysowania próbkę n_keep linii z liczbą linii proporcjonalny do frakcji wszystkich linii w obecnym kawałku. Zapewnia to równomierne próbkowanie linii w pliku. Jeśli nie ma linii do zatrzymania, przejdź do następnej porcji.

 n_tot <- n_tot + n_txt 
     n_keep <- rbinom(1, n_txt, n_txt/n_tot) 
     if (n_keep == 0L) 
      next 

Wybierz wiersze, aby utrzymać, a linie zastąpić, i zaktualizować bufor

 keep <- sample(n_txt, n_keep) 
     drop <- sample(n, n_keep) 
     buf[drop] <- txt[keep] 
    } 

Podczas wprowadzania danych jest zrobione, możemy analizować wynik przy użyciu czytnika i zwraca wynik

reader(textConnection(c(hdr, buf), header=header, ...) 
} 

Rozwiązanie może być bardziej wydajne, ale nieco bardziej skomplikowane, poprzez użycie readBin i wyszukiwanie przerw w linii, zgodnie z sugestią Simona Urbanka na temat R-devel mailing list. Oto pełne rozwiązanie:

fsample <- 
    function(fname, n, seed, header=FALSE, ..., reader = read.csv) 
{ 
    set.seed(seed) 
    con <- file(fname, open="r") 
    hdr <- if (header) { 
     readLines(con, 1L) 
    } else character() 

    buf <- readLines(con, n) 
    n_tot <- length(buf) 

    repeat { 
     txt <- readLines(con, n) 
     if ((n_txt <- length(txt)) == 0L) 
      break 

     n_tot <- n_tot + n_txt 
     n_keep <- rbinom(1, n_txt, n_txt/n_tot) 
     if (n_keep == 0L) 
      next 

     keep <- sample(n_txt, n_keep) 
     drop <- sample(n, n_keep) 
     buf[drop] <- txt[keep] 
    } 

    reader(textConnection(c(hdr, buf)), header=header, ...) 
} 
+0

Dziękujemy za opublikowanie kodu i dziękujemy za doskonałą dokumentację. Czy byłbyś w stanie wskazać mi kierunek i przykład używając 'readBin'? Dzięki! – Zach

Powiązane problemy