R ggplot2 — Не удается выделить вектор размером 128,0 Мб

#r #ggplot2

#r #ggplot2

Вопрос:

У меня есть файл размером 4,5 МБ (9 223 136 строк) со следующей информацией:

 0       0
0.0147938       3.67598e-07
0.0226194       7.35196e-07
0.0283794       1.10279e-06
0.033576        1.47039e-06
0.0383903       1.83799e-06
0.0424806       2.20559e-06
0.0465545       2.57319e-06
0.0499759       2.94079e-06
  

В каждом столбце представлено значение от 0 до 100, означающее процент. Моя цель — нарисовать графику в ggplot2, чтобы проверить процентные соотношения между ними (например, при 20% от столбца 1 какой процент достигнут для столбца 2). Вот мой R-скрипт:

 library(ggplot2)
dataset=read.table("~/R/datasets/cumul.txt.gz")
p <- ggplot(dataset,aes(V2,V1))
p <- p   geom_line()
p <- p   scale_x_continuous(formatter="percent")   scale_y_continuous(formatter="percent")
p <- p   theme_bw()
ggsave("~/R/grafs/cumul.png")
  

У меня проблема, потому что каждый раз, когда я запускаю этот R, заканчивается память, выдавая ошибку: «Не удается выделить вектор размером 128,0 Мб». Я использую 32-разрядный R на компьютере с Linux, и у меня около 4 ГБ свободной памяти.

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

Комментарии:

1. есть ли у вас какие-либо другие объекты в вашей рабочей области? Когда это происходит со мной, я обычно сохраняю нужные мне объекты, а затем перезапускаю с чистой рабочей областью. Вызов gc() также может помочь, если вы удалите ненужные объекты.

2. @richie Я запускаю чистый сеанс R, вызывая только этот скрипт: /usr/bin/R CMD BATCH --vanilla --no-timing ~/scripts/R/grafs/cumul.R ~/R/scripts_output/cumul.txt

3. скрипт создает только приведенный выше пример или создает больше объектов?

4. @richiemorrisroe Я пытаюсь запустить его (с фиктивными данными и чистой рабочей областью) на 8 ГБ оперативной памяти, 64-разрядный. Процесс достигает 6 ГБ, когда я его завершаю. Таким образом, единственный способ — ограничить размер данных.

Ответ №1:

Вы уверены, что у вас 9 миллионов строк в файле размером 4,5 МБ (редактировать: возможно, ваш файл занимает 4,5 ГБ ??)? Он должен быть сильно сжат — когда я создаю файл, размер которого составляет одну десятую размера, это 115 МБ…

 n <- 9e5
set.seed(1001)
z <- rnorm(9e5)
z <- cumsum(z)/sum(z)
d <- data.frame(V1=seq(0,1,length=n),V2=z)
ff <- gzfile("lgfile2.gz", "w")
write.table(d,row.names=FALSE,col.names=FALSE,file=ff)
close(ff)
file.info("lgfile2.gz")["size"]
  

Из предоставленной вами информации трудно определить, какие «повторяющиеся строки» у вас есть в вашем наборе данных… unique(dataset) будут извлечены только уникальные строки, но это может оказаться бесполезным. Я бы, вероятно, начал с простого уменьшения набора данных в 100 или 1000 раз:

 smdata <- dataset[seq(1,nrow(dataset),by=1000),]
  

и посмотрим, как все пойдет дальше. (редактировать: забыл запятую!)

Графическое представление больших наборов данных часто является сложной задачей. В общем, вам будет лучше:

  • каким-то образом суммируя данные перед их нанесением на график
  • использование специализированного графического типа (графики плотности, контуры, шестиугольная привязка), который уменьшает объем данных
  • использование базовой графики, которая использует модель «нарисовать и забыть» (если запись графики не включена, например, в Windows), а не графики решетки / ggplot / grid, которые сохраняют полный графический объект и затем отображают его
  • использование растровой или растровой графики (PNG и т.д.), Которые записывают только состояние каждого пикселя изображения, а не векторной графики, которая сохраняет все объекты независимо от того, перекрываются они или нет

Комментарии:

1. Ваши первые два пункта являются наиболее важными (и эквивалентны) — если вы соответствующим образом обобщите данные, скорость отрисовки базы по сравнению с сеткой не будет иметь значения.

2. @hadley: достаточно справедливо. С точки зрения начинающего пользователя, может быть разница между машиной черного ящика для суммирования и построения данных за один шаг (соответствующее использование sum_stat() , plot(density(x)) и т.д.) И необходимостью делать сводку самостоятельно. Я согласен, что более элегантно и в долгосрочной перспективе более эффективно найти способы суммирования данных, хотя # 3 и # 4 могут быть полезны для рассмотрения при кратковременном взломе.