2010-12-02 4 views
23

Как я могу построить очень большой набор данных в R?Построение очень больших наборов данных в R

Я хотел бы использовать коробку или скрипичный сюжет или подобное. Все данные не могут быть помещены в память. Могу ли я поэтапно читать и вычислять резюме, необходимые для составления этих графиков? Если да, то как?

+1

Что именно означает «очень большой» в вашем случае? – radek 2010-12-03 11:55:39

+3

@radek: «Все данные не могут быть помещены в память», похоже на хорошее приближение «слишком большого для обработки R». Является ли это 2Gb или 20Gb больше не имеет значения, не так ли? – 2010-12-03 14:23:46

+1

@ Joris Если OP не имеет memory.limit слишком мало или много ненужных столбцов или что-то еще. Эта информация может быть актуальной. – Marek 2010-12-03 16:38:15

ответ

10

В дополнении к моему комментарию к Dmitri answer, функции для вычисления квантилей с использованием обработки ff больших пакета данных:

ffquantile<-function(ffv,qs=c(0,0.25,0.5,0.75,1),...){ 
stopifnot(all(qs<=1 & qs>=0)) 
ffsort(ffv,...)->ffvs 
j<-(qs*(length(ffv)-1))+1 
jf<-floor(j);ceiling(j)->jc 
rowSums(matrix(ffvs[c(jf,jc)],length(qs),2))/2 
} 

Это точный алгоритм, поэтому он использует сортировку - и, таким образом, может уделите много времени.

3

Все, что вам нужно для ящика, это квантиль, крайности «вискера» и выбросы (если показаны), которые легко вычисляются заранее. Взгляните на функцию boxplot.stats.

2

Вы можете создавать участки из управляемой выборки ваших данных. Например. если вы используете только 10% случайно выбранных строк, тогда boxplot на этом образце не должен отличаться от ящика для всех данных.

Если ваши данные находятся в некоторой базе данных, вы можете создать некоторый случайный флаг (поскольку я знаю, что почти каждый движок базы данных имеет какой-то генератор случайных чисел).

Во-вторых, насколько велик ваш набор данных? Для boxplot вам нужны два столбца: переменная значения и групповая переменная. Этот пример:

N <- 1e6 
x <- rnorm(N) 
b <- sapply(1:100, function(i) paste(sample(letters,40,TRUE),collapse="")) 
g <- factor(sample(b,N,TRUE)) 
boxplot(x~g) 

Требуется 100 МБ ОЗУ. Если N=1e7, то он использует < 1 ГБ ОЗУ (который по-прежнему управляется современной машиной).

2

Это интересная проблема.

Коробки требуют квантили. Вычисление квантилей на очень больших наборах данных является сложным.

Простейшее решение, которое может или не может работать в вашем случае, состоит в том, чтобы сначала сбрасывать данные и создавать графики образца. Другими словами, читайте кучу записей за раз и сохраняйте подмножество из них в памяти (выбираете либо детерминистически, либо случайным образом). В конце создавайте графики на основе данных, которые были сохранены в памяти. Опять же, насколько это жизнеспособно, очень многое зависит от свойств ваших данных.

В качестве альтернативы существуют алгоритмы, которые могут экономично и приблизительно вычислять квантили в режиме «онлайн», что означает, что они представлены одним наблюдением за раз, и каждое наблюдение отображается ровно один раз. Хотя у меня есть ограниченный опыт работы с такими алгоритмами, я не видел никаких доступных реализаций R.

В следующем документе представлен краткий обзор некоторых соответствующих алгоритмов: Quantiles on Streams.

8

Проблема в том, что вы не можете загрузить все данные в память. Таким образом, вы можете делать выборку данных, как указано ранее в @Marek. На таких огромных наборах данных вы получаете практически те же результаты, даже если вы берете только 1% данных. Для скрипичного сюжета это даст вам достойную оценку плотности. Прогрессивный расчет квантилей невозможен, но это должно дать очень приличное приближение. Это по существу то же самое, что и «рандомизированный метод», описанный в ссылке @aix.

Если вы не можете подмножить дату вне R, это можно сделать, используя соединения в сочетании с sample(). Следующей функцией является то, что я использую для отбора данных из фрейма данных в текстовом формате, когда он становится слишком большим. Если вы немного поиграете с соединением, вы можете легко преобразовать его в socketConnection или другое, чтобы прочитать его с сервера, базы данных, что угодно. Просто убедитесь, что вы открываете соединение в правильном режиме.

Хорошо, сделайте простой.CSV файл, а затем следующие образцы функций доля р данных:

sample.df <- function(f,n=10000,split=",",p=0.1){ 
    con <- file(f,open="rt",) 
    on.exit(close(con,type="rt")) 
    y <- data.frame() 
    #read header 
    x <- character(0) 
    while(length(x)==0){ 
     x <- strsplit(readLines(con,n=1),split)[[1]] 
    } 
    Names <- x 
    #read and process data 
    repeat{ 
     x <- tryCatch(read.table(con,nrows=n,sep=split),error = function(e) NULL) 
     if(is.null(x)) {break} 
     names(x) <- Names 
     nn <- nrow(x) 
     id <- sample(1:nn,round(nn*p)) 
     y <- rbind(y,x[id,]) 
    } 
    rownames(y) <- NULL 
    return(y) 
} 

Пример использования:

#Make a file 
Df <- data.frame(
    X1=1:10000, 
    X2=1:10000, 
    X3=rep(letters[1:10],1000) 
) 
write.csv(Df,file="test.txt",row.names=F,quote=F) 

# n is number of lines to be read at once, p is the fraction to sample 
DF2 <- sample.df("test.txt",n=1000,p=0.2) 
str(DF2) 

#clean up 
unlink("test.txt") 
4

Вы также должны смотреть на RSQLite, SQLiteDF, RODBC и biglm пакетов. Для больших наборов данных может быть полезно хранить данные в базе данных и вытаскивать только фрагменты в R. Базы данных также могут сортировать для вас, а затем вычислять квантили для отсортированных данных намного проще (тогда просто используйте квантиль для выполнения графиков) ,

Существует также пакет hexbin (bioconductor) для выполнения эквивалентов рассеивающей диаграммы с очень большими наборами данных (возможно, все еще требуется использовать образец данных, но работает с большим образцом).

Смежные вопросы