Построение очень больших наборов данных в R - PullRequest
25 голосов
/ 03 декабря 2010

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

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

Ответы [ 8 ]

10 голосов
/ 03 декабря 2010

В дополнение к моему комментарию к Ответ Дмитрия , функция для вычисления квантилей с использованием 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
}

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

8 голосов
/ 03 декабря 2010

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

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

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

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 голосов
/ 03 декабря 2010

Вы можете поместить данные в базу данных и рассчитать квантили, используя SQL. Смотри: http://forge.mysql.com/tools/tool.php?id=149

4 голосов
/ 03 декабря 2010

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

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

3 голосов
/ 03 декабря 2010

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

2 голосов
/ 03 декабря 2010

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

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

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

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

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

2 голосов
/ 03 декабря 2010

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

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

Во-вторых, насколько велик ваш набор данных?Для 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 ГБ ОЗУ (что по-прежнему доступно для современной машины). </p>

0 голосов
/ 02 ноября 2018

Возможно, вы можете подумать об использовании disk.frame, чтобы сначала суммировать данные перед началом построения?

...