Добрый день! Я использую такой код, который не только подписывает ось значениями даты-времени, но и автоматически подбирает подходящий шаг между главными и вспомогательными делениями оси, а также формат подписей. Для работы нужны значения минимума-максимума по оси (в формате Unix, секунды) и ориентировочное число главных делений на ней (по умолчанию — 10). В примере с помощью функции ggplot строется матрица спектрограммы, где по горизонтальной оси откладывается время, по вертикальной — частота, цвет пикселей растра — амплитуда).
Код: Выделить всё
# Главная функция
TickList <- Ticks.POSIX(MinMax(dfData$t), 10)
h <- ggplot(data = dfData,
mapping = aes(x = t, y = f, fill = v))
h <- h + geom_raster(interpolate = TRUE)
h <- h + scale_x_datetime(breaks = TickList$Ticks,
date_labels = TickList$Format,
minor_breaks = TickList$SubTicks)
print(h)
# Функция подбора оптимальных подписей по временной шкале
Ticks.POSIX <- function(IntU, IntN = 10)
# IntU - вектор из двух значений в формате UNIX (пределы оси)
# IntN - желаемое число делений на оси
# Функция возвращает вектор делений,
# округлённых до ближайшего временного интервала, в формате POSIX
{
L <- seq(from = IntU[1], to = IntU[2], length.out = IntN)
Step <- ChooseStep(L[2]-L[1])
TicksP <- TickSeq.POSIX(IntU, Step$Main)
if (Step$Main > 10*24*60*60) # Шаг больше 10 суток
for (TickI in 1:length(TicksP))
{
TicksLP <- as.POSIXlt(TicksP[TickI])
DayOfMonth <- as.numeric(TicksLP$mday)
if (DayOfMonth > 14)
{
Month <- as.numeric(TicksLP$mon)
if (Month == 12)
{
Year <- as.number(TicksLP$year)
TicksLP$year <- as.character(Year+1)
TicksLP$mon <- '1'
}
else
TicksLP$mon <- as.character(Month+1)
}
TicksLP$mday <- '1'
TicksLP$hour <- '0'
TicksLP$min <- '0'
TicksLP$sec <- '0'
TicksP[TickI] <- as.POSIXct(TicksLP)
}
SubTicksP <- TickSeq.POSIX(IntU, Step$Sub)
return(list(Ticks = TicksP,
Format = Step$Format,
SubTicks = SubTicksP))
}
#
# Выбор подходящего шага и формата
ChooseStep <- function(DL)
# DL — пределы оси в формате UNIX
{
S <- 1; M <- S*60; H <- M*60; D <- H*24; L <- D*30.4375; Y <- D*365.24
St <- c(0.2*S, 0.4*S, 1*S, 2*S, 4*S,
10*S, 20*S, 30*S, 1*M, 2*M,
4*M, 10*M, 20*M, 30*M, 1*H,
2*H, 4*H, 6*H, 12*H, 1*D,
2*D, 5*D, 10*D, 20*D, 1*L,
2*L, 4*L, 6*L, 1*Y, 2*Y)
SSt <- c(0.1*S, 0.2*S, 0.5*S, 1*S, 2*S,
5*S, 10*S, 10*S, 30*S, 1*M,
2*M, 5*M, 10*M, 10*M, 30*M,
1*H, 2*H, 2*H, 6*H, 12*H,
1*D, 1*D, 5*D, 10*D, 0.5*L,
1*L, 2*L, 2*L, 6*L, 1*Y)
Frm <- c('%H:%M:%OS2', '%H:%M:%OS2', '%H:%M:%S', '%H:%M:%S', '%H:%M:%S',
'%H:%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M:%S',
'%H:%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M:%S', '%d %b %H:%M',
'%d %b %H:%M','%d %b %H:%M','%d %b %H:%M','%d %b %H:%M','%d-%m-%y',
'%d-%m-%y', '%d-%m-%y', '%d-%m-%y', '%d-%m-%y', '%b %Y',
'%b %Y', '%b %Y', '%b %Y', '%b %Y', '%Y')
I <- which.min(abs(St-DL))
return(list(Main = St[I], Sub = SSt[I], Format = Frm[I]))
}
#
# Генерация последовательности делений временной шкалы
TickSeq.POSIX <- function(IntU, Step)
{
First <- Step*ceiling(IntU[1]/Step);
Last <- Step*floor(IntU[2]/Step);
TicksU <- seq(from = First, to = Last, by = Step)
TicksP <- as.POSIXct(x = TicksU,
origin = "1970-01-01",
tz = "GMT")
return(TicksP)
}
# Минимум и максимум за один раз
MinMax <- function(X)
return(c(min(X, na.rm = TRUE), max(X, na.rm = TRUE)))