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, ...)
}
Co z przykładową zawartością pliku? –
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ć. –
Więcej informacji byłoby dobrze, ale dlaczego nie zaimportować go do SQL, zrobić tam jakieś przygotowanie, a następnie załadować do R? –