Самый быстрый и гибкий способ составить график более 2 миллионов строк данных плоских файлов? - PullRequest
29 голосов
/ 25 февраля 2011

Я собираю некоторые системные данные в плоский файл, который имеет следующий формат:

YYYY-MM-DD-HH24:MI:SS DD1 DD2 DD3 DD4

Где DD1-DD4 - четыре элемента данных. Пример файла такой:

2011-02-01-13:29:53 16 8 7 68
2011-02-01-13:29:58 13 8 6 110
2011-02-01-13:30:03 26 25 1 109
2011-02-01-13:30:08 13 12 1 31
2011-02-01-13:30:14 192 170 22 34
2011-02-01-13:30:19 16 16 0 10
2011-02-01-13:30:24 137 61 76 9
2011-02-01-13:30:29 452 167 286 42
2011-02-01-13:30:34 471 177 295 11
2011-02-01-13:30:39 502 192 309 10

Файл содержит более 2 миллионов строк с точками данных каждые пять секунд.

Мне нужно наметить эти данные, чтобы иметь возможность извлечь из них смысл.

Что я пробовал

В данный момент я пробовал gnuplot и rrdtool с различными инструментами Unix (awk, sed и т. Д.). Обе они работают, но, похоже, требуют много разбора и пересчета данных каждый раз, когда я хочу просмотреть их по-другому. Мне кажется, что rrdtool - верный путь, но в данный момент я изо всех сил пытаюсь получить данные в него достаточно быстро, отчасти потому, что мне нужно преобразовать свою метку времени в эпоху Unix. Я также понимаю, что если я решу, что хочу новую гранулярность агрегации, мне придется перестраивать rrd (что имеет смысл для сбора в реальном времени, но не для ретроспективных загрузок, подобных этой) Эти вещи заставляют меня думать, что, возможно, я использую не тот инструмент.

Сбор данных в плоский файл исправлен - например, я не могу передать коллекцию напрямую в rrdtool.

Мой вопрос

Мне бы хотелось, чтобы мнения людей о наилучшем способе составления графиков. У меня есть эти требования:

  1. Создание графика должно быть максимально быстрым (не только рендерингом, но и настройкой рендеринга)
  2. Он должен быть максимально гибким - мне нужно работать с графиками, чтобы работать лучшая гранулярность для данных (5 секунд, вероятно, слишком гранулярно)
  3. Он должен быть в состоянии агрегировать (MAX / AVG / и т. Д.), Где это необходимо.
  4. Должны быть повторяемые и новые файлы данных по мере их поступления
  5. В идеале я хочу иметь возможность накладывать DD1 против DD2 или DD1 на прошлой неделе с DD1 на этой неделе
  6. Unix или Windows, все равно. Предпочитаю * nix хотя: -)

Есть предложения?

Ответы [ 3 ]

26 голосов
/ 25 февраля 2011

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

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

  1. Импорт данных в R. ( R Import Export Guide )
  2. Получите данные в соответствующую структуру временных рядов. ( виньетка XTS PDF )
  3. Немного прорисовки. ( Краткое знакомство с графикой )

Вот пример кода с использованием точек 2 мм. Если вы заметили, я не иллюстрирую нанесение всех точек 2 мм. Это медленно и не очень информативно. Но это должно дать вам несколько идей по началу работы. Не стесняйтесь возвращаться с более конкретными вопросами, если вы решите прыгнуть в кроличью нору R!

require( xts )
require( lubridate )

## set up some example data
dataLength <- 2e6
startTime <- ymd_hms("2011-02-01-13-29-53")
fistFullOfSeconds <- 1:dataLength
date <- startTime + fistFullOfSeconds
DD1 <- rnorm( dataLength )
DD2 <- DD1 + rnorm(dataLength, 0, .1 )
DD3 <- rnorm( dataLength, 10, 2)
DD4 <- rnorm( dataLength )

myXts <- xts(matrix( c( DD1, DD2, DD3, DD4 ), ncol=4 ), date)

## now all the data are in the myXts object so let's do some
## summarizing and visualization

## grabbing just a single day from the data
## converted to data.frame to illustrate default data frame plotting
oneDay <- data.frame( myXts["2011-02-02"] ) 
plot( oneDay )

Отношения между DD1 и DD2 вроде как выпрыгивают
enter image description here

boxplot( oneDay )

Boxplot - это круговая диаграмма статистической графики. Сюжет, который вы любите ненавидеть. Возможно, ссылка на этот пока мы здесь. enter image description here

## look at the max value of each variable every minute
par(mfrow=c(4,1)) ## partitions the graph window
ep <- endpoints(myXts,'minutes')
plot(period.apply(myXts[,1],INDEX=ep,FUN=max))
plot(period.apply(myXts[,2],INDEX=ep,FUN=max))
plot(period.apply(myXts[,3],INDEX=ep,FUN=max))
plot(period.apply(myXts[,4],INDEX=ep,FUN=max))

Даже при одноминутном разрешении я не уверен, что это информативно. Должно быть подмножество. enter image description here

9 голосов
/ 25 февраля 2011

Вот некоторый код R для игры с 8000000 числами в 4 столбцах 2000000 строк:

> d=matrix(runif(8000000),ncol=4)
> dim(d)
[1] 2000000       4
> plot(d[1:1000,1])
> plot(d[1:1000,1],type='l')
> plot(d[1:10000,1],type='l')

теперь он начинает немного замедляться:

> plot(d[1:100000,1],type='l')

как насчет соотношения двух столбцов:

> cor(d[,1],d[,2])
[1] 0.001708502

- мгновенно. Преобразование Фурье?

> f=fft(d[,1])

также мгновенно. Но не пытайтесь изобразить это.

Давайте нарисуем прореженную версию одного из столбцов:

> plot(d[seq(1,2000000,len=1000),1],type='l')

- мгновенно.

Чего на самом деле не хватает, так это интерактивного графика, где вы можете масштабировать и перемещать весь набор данных.

5 голосов
/ 25 февраля 2011

Ниже приведен пример данных, загруженных в R, агрегированных и т. Д. ...

Сначала несколько фиктивных данных для записи в файл:

stime <- as.POSIXct("2011-01-01-00:00:00", format = "%Y-%d-%m-%H:%M:%S")
## dummy data
dat <- data.frame(Timestamp = seq(from = stime, by = 5, length = 2000000),
                  DD1 = sample(1:1000, replace = TRUE),
                  DD2 = sample(1:1000, replace = TRUE),
                  DD3 = sample(1:1000, replace = TRUE),
                  DD4 = sample(1:1000, replace = TRUE))
## write it out
write.csv(dat, file = "timestamp_data.txt", row.names = FALSE)

Тогда мы можем отсчитывать время в 2 миллиона строк.Чтобы ускорить это, мы сообщаем R классы столбцов в файле: "POSIXct" - это один из способов в R для хранения типа временных меток, которые у вас есть.

## read it in:
system.time({
             tsdat <- read.csv("timestamp_data.txt", header = TRUE,
                                 colClasses = c("POSIXct",rep("integer", 4)))
            })

, который занимает около 13 секунд, чтобычитать и форматировать во внутреннем Unix раз на моем скромном ноутбуке.

   user  system elapsed 
 13.698   5.827  19.643 

Агрегирование может быть выполнено множеством способов, один из которых использует aggregate().Скажите совокупное значение за среднее / среднее значение часа:

## Generate some indexes that we'll use the aggregate over
tsdat <- transform(tsdat,
                   hours   = factor(strftime(tsdat$Timestamp, format = "%H")),
                   jday    = factor(strftime(tsdat$Timestamp, format = "%j")))
## compute the mean of the 4 variables for each minute
out <- aggregate(cbind(Timestamp, DD1, DD2, DD3, DD4) ~ hours + jday, 
                 data = tsdat, FUN = mean)
## convert average Timestamp to a POSIX time
out <- transform(out,
                 Timestamp = as.POSIXct(Timestamp, 
                                        origin = ISOdatetime(1970,1,1,0,0,0)))

Это (строка, создающая out) занимает ~ 16 секунд на моем ноутбуке и дает следующий вывод:

> head(out)
  hours jday           Timestamp      DD1      DD2      DD3      DD4
1    00  001 2010-12-31 23:29:57 500.2125 491.4333 510.7181 500.4833
2    01  001 2011-01-01 00:29:57 516.0472 506.1264 519.0931 494.2847
3    02  001 2011-01-01 01:29:57 507.5653 499.4972 498.9653 509.1389
4    03  001 2011-01-01 02:29:57 520.4111 500.8708 514.1514 491.0236
5    04  001 2011-01-01 03:29:57 498.3222 500.9139 513.3194 502.6514
6    05  001 2011-01-01 04:29:57 515.5792 497.1194 510.2431 496.8056

Простое построение графиков может быть достигнуто с помощью функции plot():

plot(DD1 ~ Timestamp, data = out, type = "l")

. Мы можем наложить больше переменных, например:

ylim <- with(out, range(DD1, DD2))
plot(DD1 ~ Timestamp, data = out, type = "l", ylim = ylim)
lines(DD2 ~ Timestamp, data = out, type = "l", col = "red")

или через несколько панелей:

layout(1:2)
plot(DD1 ~ Timestamp, data = out, type = "l", col = "blue")
plot(DD2 ~ Timestamp, data = out, type = "l", col = "red")
layout(1)

Все это было сделано с функциональностью base R.Другие показали, как пакеты дополнений могут упростить работу с датами.

...