Самый быстрый и наиболее гибкий способ отображать более 2 миллионов строк данных плоского файла?
Я собираю некоторые системные данные в файле flatfile, который имеет этот формат:
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.
Мой вопрос
Я бы хотел, чтобы мнения людей касались наилучшего способа создания диаграмм. У меня есть следующие требования:
- Это должно быть как можно быстрее, чтобы создать график (а не просто визуализировать, но настроить для рендеринга тоже)
- Он должен быть как можно более гибким - мне нужно гасить вокруг, чтобы графики работали
(5 секунд, вероятно, слишком зернистые)
- Он должен иметь возможность суммировать (MAX/AVG/etc), где необходимо
- Это должны быть повторяемые и новые файлы данных, поскольку они входят в
- В идеале я хочу иметь возможность накладывать DD1 на DD2 или DD1 на прошлой неделе с DD1 на этой неделе.
- Unix или Windows, все равно. Предпочитаю * nix, хотя: -)
Любые предложения?
Ответы
Ответ 1
Это действительно хороший вопрос. Я рад видеть, что некоторые люди R взвешивают. Я тоже думаю, что R - правильный инструмент для работы, хотя это мой главный молот, поэтому все выглядит немного как гвоздь для меня.
Существует несколько концепций R, необходимых для решения этой проблемы. Как я вижу, вам нужно следующее (ссылки в parens):
Вот пример кода с использованием 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 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]()
Ответ 2
Здесь некоторый 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')
- мгновенный.
То, что действительно отсутствует, - это интерактивный сюжет, где вы можете масштабировать и панорамировать весь набор данных.
Ответ 3
Вот пример по строкам данных, которые у вас есть, загруженные в 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)
Все это было сделано с базовыми функциями R. Другие показали, как дополнительные пакеты могут облегчить работу с датами.