Построение графиков с датами в R

Вопросы по статистическому пакету R. Не обязательно гео.
Ответить
oda412
Новоприбывший
Сообщения: 13
Зарегистрирован: 01 июл 2020, 11:43
Репутация: 0
Откуда: Брёхово

Построение графиков с датами в R

Сообщение oda412 » 01 июл 2020, 13:05

Здравствуйте! У меня есть данные с интервалом записи по 1 секунде. Но дата и время представлены в виде числа секунд от 1 января 1900 года (из excel). Когда я строю графики - по оси x отображаются эти числа. Подскажите, пожалуйста, как поменять формат надписей по оси x, чтобы вместо числа отображалась дата со временем в формате "%d-%m-%Y %H:%M:%S"?

Пробовала as.Date(k,origin="1900-01-01"). Но при построении графика plot(k,t1[,2],type="l") по оси x вообще вывалились дни недели...

Благодарю за совет!

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 01 июл 2020, 14:05

Добрый день! Я использую такой код, который не только подписывает ось значениями даты-времени, но и автоматически подбирает подходящий шаг между главными и вспомогательными делениями оси, а также формат подписей. Для работы нужны значения минимума-максимума по оси (в формате 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)))
Последний раз редактировалось Константин Силкин 01 июл 2020, 16:25, всего редактировалось 5 раз.

oda412
Новоприбывший
Сообщения: 13
Зарегистрирован: 01 июл 2020, 11:43
Репутация: 0
Откуда: Брёхово

Re: Построение графиков с датами в R

Сообщение oda412 » 01 июл 2020, 14:57

Константин Силкин, спасибо большое !!
Скажите, а есть ли команда, которая формат надписей оси быстро меняет с числового на даты?

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 01 июл 2020, 15:05

Удачи!
Функции as.POSIX*(). В моём примере as.POSIXct

oda412
Новоприбывший
Сообщения: 13
Зарегистрирован: 01 июл 2020, 11:43
Репутация: 0
Откуда: Брёхово

Re: Построение графиков с датами в R

Сообщение oda412 » 01 июл 2020, 15:39

Константин Силкин, поняла, спасибо!

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 01 июл 2020, 16:26

Смотрите только, у меня счёт секунд ведётся с 1 января 1970 года

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 02 июл 2020, 01:33

oda412 писал(а):
01 июл 2020, 14:57
Скажите, а есть ли команда, которая формат надписей оси быстро меняет с числового на даты?
Еще в пакете lubridate есть такие функции
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 02 июл 2020, 08:15

Если вы имеет в виду функцию pretty_dates, то она только определяет местоположение "красивых" меток, а об их формате придётся позаботиться самому

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 05 июл 2020, 14:59

В пакете ggplot2 оказывается есть специальные функции для настройки вида шкалы осей времени.
В данном случае подойдет:
scale_x_datetime(breaks = date_breaks("3 hour"), labels = date_format("%H:%M"))

Аргумент labels= рекомендуется использовать в паре с функцией date_format() из пакета scales, выполняющей форматирование дат в соответствии с форматом POSIX.

Только, что случайно нашел. Может быть пригодится.
Последний раз редактировалось VistaSV30 06 июл 2020, 11:07, всего редактировалось 1 раз.
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 05 июл 2020, 17:21

Да, хорошая возможность. В примере кода наверху в строке 6 она используется

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 06 июл 2020, 15:28

Подскажите, пожалуйста, в чём ошибка?
Не получается подписи оси X вывести в формате - "%H:%M".
Ошибка: Invalid input: date_trans works with objects of class Date only

Код: Выделить всё

th <- sample(0:23, 1000, replace = TRUE)
tm <- sample(0:59, 1000, replace = TRUE)
dt <- rnorm(1000, mean = 10, sd = 4)

df <- data.frame(th, tm, dt)
df$t1 <- as.POSIXct(paste0(df$th, ":", df$tm), format = "%H:%M")

library(ggplot2)
library(scales)
ggplot(df, aes(x = t1, y = dt)) + geom_point() +
  scale_x_date(breaks = date_breaks("3 hours"),
    labels = date_format("%H:%M"))
Пробовал менять форматы даты - бесполезно.
Буквально вчера всё получалось.

Так формат меток меняется, но они смещаются по оси X

Код: Выделить всё

ggplot(df, aes(x = t1, y = dt)) + geom_point() +
  scale_x_time(breaks = date_breaks("4 hours"),
    labels = time_format("%H:%M"))
Последний раз редактировалось VistaSV30 06 июл 2020, 15:54, всего редактировалось 1 раз.
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Константин Силкин
Завсегдатай
Сообщения: 420
Зарегистрирован: 21 мар 2012, 07:37
Репутация: 67
Откуда: Воронеж

Re: Построение графиков с датами в R

Сообщение Константин Силкин » 06 июл 2020, 15:54

Добрый день! Формат POSIX предусматривает полную дату-время, а вы только время задаёте. Озаботьтесь и датой тоже. Хотя по умолчанию должна текущая дата подставляться, но видимо у вас именно это умолчание и не работает

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 06 июл 2020, 15:57

Вроде бы нашел решение.

Оказывается, такое смещение оси возникало из-за параметра tz - часовой пояс.
Для Балашихи :lol: оказалось должно быть:
labels = time_format("%H:%M", tz = "Europe/Kaliningrad"),

Значение моего tz определил функцией Sys.timezone(location = TRUE)

Мне нужно, чтоб код работал одинаково на всей территории России

Попробуйте пожалуйста в других часовых поясах будет работать?
На своем компьютере менял часовой пояс - работает корректно, но вдруг в другом часовом поясе не сработает.

Код: Выделить всё

th <- sample(0:23, 1000, replace = TRUE)
tm <- sample(0:59, 1000, replace = TRUE)
dt <- rnorm(1000, mean = 10, sd = 2)

df <- data.frame(th, tm, dt)
df$t1 <- as.POSIXct(paste0(df$th, ":", df$tm), format = "%H:%M")


library(ggplot2)
library(scales)
ggplot(df, aes(x = t1, y = dt)) + geom_point() +
  scale_x_time(breaks = date_breaks("3 hours"),
    labels = time_format("%H:%M", tz = Sys.timezone(location = TRUE)),
    expand = c(0,0)
  )
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 17 июл 2020, 23:42

Добрый вечер!
Еще один небольшой вопрос по диаграммам с датой.
Чтобы совместить показатели за 2018 и 2019 год, я преобразовал даты в числа, соответствующие порядковому номеру дня в году - от 1 до 365 и построил такую диаграмму:
Изображение

Код: Выделить всё

 ggplot(n, aes(x = Dd, y = Fire, colour = as.factor(Yr))) +
  geom_line()
Теперь надо, чтобы по оси X отображались даты, а не порядковые номера дней.

Проблема решена. Создал еще один столбец в таблице с датами, мне же на диаграмме нужны только даты и месяцы

Код: Выделить всё

library(lubridate)
n$Yr <- year(n$Date)
n$Dd <- as.Date(yday(n$Date), origin = "1900-01-01")

# Диаграмма
library(ggplot2)
library(scales)
ggplot(n, aes(x = Dd, y = Fire, colour = as.factor(Yr))) +
  geom_line(size = 0.92) +
  labs(x="Дата", y="Кол-во пожаров, ед.", color = "Год") +
  theme(legend.position = c(0.92,0.9)) +
  scale_x_date(breaks = date_breaks("2 months"), date_labels = "%d\n%b") # Форматирование оси X

Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Построение графиков с датами в R

Сообщение VistaSV30 » 21 авг 2020, 21:52

Подскажите еще раз пожалуйста! В чем ошибка?
По оси X откладываются минуты от 0 до 1439 (одни сутки). Почему-то не получается отформатировать метки в формате HH:MM

Код: Выделить всё

D <- data.frame(Time = 0:1439, G = 1:1440)

library(ggplot2)
library(scales)
library(lubridate)

D$Tm <- as.POSIXct(D$Time, origin = "1970-01-01", tz = "GMT")
ggplot(D, aes(x = Tm, y = G)) + 
  geom_line() +
  scale_x_time(breaks = date_breaks("3 hours"),
               labels = time_format("%H:%M", tz = "GMT"),
               name = "hh:mm")
Проблема решена! Просто шаг по оси X был задан в секундах, а надо в минутах.
D <- data.frame(Time = seq(0, 86340, by = 60), G = 1:1440)
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Ответить

Вернуться в «R»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 12 гостей