Постройте несколько временных рядов один под другим, используя R

#r #ggplot2

#r #ggplot2

Вопрос:

Я хочу получить график, подобный этому, имея каждый канал временного ряда ээг ниже другого, используя пространство для построения графика как можно лучше, поскольку имеется 64 канала. Вот изображение. мне интересны столбцы 1, 2 и 4:

введите описание изображения здесь

На данный момент я использую gg plot и facet wrap, которые тратят так много места на метки и оси. Простого графика, подобного первому столбцу, будет достаточно для сравнения разных каналов друг с другом.

Вот мой текущий код:

 library(ggplot2)
library(reshape2)

X1 <- c(1,2,3,4,5,6,7,8,9,19)
X2 <- c(1,4,2,4,1,4,1,4,1,4)
X3 <- c(1,2,3,4,5,6,7,8,9,10)
X4 <- c(1,2,3,4,5,6,7,8,9,1)
X5 <- c(1,4,2,4,1,4,1,4,1,4)
X6 <- c(1,2,3,4,5,6,7,8,9,10)
X7 <- c(1,2,3,4,5,6,7,8,9,11)
X8 <- c(1,4,2,4,1,4,1,4,1,4)
X9 <- c(1,2,3,4,5,6,7,8,9,10)
X10 <- c(1,2,3,4,5,6,7,8,9,10)

icaFrame <- data.frame(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10)

scale <- rep.int(c(1:10),10)


df_melt = melt(icaFrame[,1:10])
ggplot(df_melt, aes(x = scale, y = value))   
  geom_line()   
  facet_wrap(~ variable, scales = 'free_y', ncol = 1)
 

Итак, как я могу создать такой простой график, чтобы каждый временной ряд был нанесен ниже другого, используя R?

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

1. Можете ли вы улучшить пример набора данных (его нет icaFrame )?

2. @PoGibas Я обновил свой код, чтобы исправить это

Ответ №1:

РЕДАКТИРОВАТЬ: добавлен другой подход внизу для более плотной упаковки, если нерегулярный интервал в порядке.

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

 scaling_factor = 2.5  # Adjust this to make more or less room between series

ggplot(df_melt, aes(x = scale, group = variable,
                    y = value   as.numeric(variable) * scaling_factor))   
  geom_line()  
  scale_y_continuous(breaks = (as.numeric(df_melt$variable)   0.5) * scaling_factor,
                     labels = df_melt$variable, minor_breaks = NULL)  
  labs(y="")
 

введите описание изображения здесь


Вот другой подход, который находит минимально необходимый интервал между каждым рядом, чтобы избежать каких-либо перекрытий.

 library(dplyr)
min_space = 2
vertical_shift <- df_melt %>%
  # Add scale as a variable for use in next step
  group_by(variable) %>% mutate(scale = row_number()) %>% ungroup() %>%
  # Group by scale and track gap vs. prior variable
  group_by(scale) %>% mutate(gap = value - lag(value, default = 0)) %>% ungroup() %>%
  # Group by variable and find minimum gap
  group_by(variable) %>% 
  summarize(gap_needed_below = 1 - min(gap)   min_space) %>%
  ungroup() %>%
  mutate(cuml_gap = cumsum(gap_needed_below))

df_melt %>%
  group_by(variable) %>% mutate(scale = row_number()) %>% ungroup() %>%
  left_join(vertical_shift) %>%
  mutate(shifted_value = value   cuml_gap) %>%
ggplot(aes(x = scale, group = variable,
           y = shifted_value))   
  geom_line()  
  scale_y_continuous(breaks = vertical_shift_headers$cuml_gap   1,
                     labels = vertical_shift_headers$variable,
                     minor_breaks = NULL)  
  labs(y="")
 

введите описание изображения здесь

Ответ №2:

Я думаю, вы были довольно близки. Я буду использовать data.table только для получения числа, необходимого для обозначения оси y, но вы можете использовать любой другой инструмент base или dplyr. Я также буду использовать некоторые фиктивные данные, которые позволят нам лучше видеть результат (ваши данные пересекают значения, в отличие от изображения, которое вы вставили).

 # load libraries

library(data.table)
library(ggplot2)

# create dummy data

set.seed(1)
dt <- data.table(time = 1:10, 
                 EOG = sample(1:5, 10, TRUE), 
                 Pz = sample(6:10, 10, TRUE), 
                 Cz = sample(15:21, 10, TRUE))

# melt that data

melt_dt <- melt(dt, id.vars = 1)

# find mean values for each variable

crossings <- melt_dt[, mean(value), by = variable]
 

Теперь постройте все это:

 ggplot(melt_dt, 
       aes(x = time, 
           y = value, 
           group = variable)) 
   geom_line() 
   scale_y_continuous(breaks = crossings$V1, 
                      labels = crossings$variable)
 

Который производит:

Построение

Ответ №3:

Я думаю, что мне удалось получить что-то близкое к первому столбцу, используя фасеты. Чтобы поместить имена фасетов по оси y, используйте strip.position = 'left' функцию facet . Это сэкономит много места.

Затем, чтобы ближе взглянуть на первый столбец, вам нужно поиграть с theme() элементами.

 library(ggplot2)
library(reshape2)

X1 <- c(1,2,3,4,5,6,7,8,9,19)
X2 <- c(1,4,2,4,1,4,1,4,1,4)
X3 <- c(1,2,3,4,5,6,7,8,9,10)
X4 <- c(1,2,3,4,5,6,7,8,9,1)
X5 <- c(1,4,2,4,1,4,1,4,1,4)
X6 <- c(1,2,3,4,5,6,7,8,9,10)
X7 <- c(1,2,3,4,5,6,7,8,9,11)
X8 <- c(1,4,2,4,1,4,1,4,1,4)
X9 <- c(1,2,3,4,5,6,7,8,9,10)
X10 <- c(1,2,3,4,5,6,7,8,9,10)

icaFrame <- data.frame(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10)

scale <- rep.int(c(1:10),10)

df_melt <- melt(icaFrame[,1:10])

ggplot(df_melt, aes(x = scale, y = value))   
  geom_line()   
  # remove extra space in x axis
  scale_x_continuous(expand=c(0,0))  
  # standard black and white background theme 
  theme_bw()  
  # customized theme elements (you can play around with them to get a better look:
  theme(axis.title = element_blank(),              # remove labels from axis
        panel.spacing = unit(0, units = 'points'), # remove spacing between facet panels
        panel.border = element_blank(),            # remove border in each facet
        panel.grid.major.y=element_blank(),        # remove grid lines from y axis
        panel.grid.minor.y=element_blank(),
        axis.line = element_line(),                # add axis lines to x and y
        axis.text.y=element_blank(),               # remove tick labels from y axis
        axis.ticks.y = element_blank(),            # remove tick lines from y axis
        strip.background = element_blank(),        # remove gray box from facet title
        # change rotation and alignment of text in facet title
        strip.text.y = element_text(angle = 180,   
                                  face = 'bold',
                                  hjust=1,
                                  vjust=0.5),
        # place facet title to the left of y axis
        strip.placement = 'outside'
        )  
  # call facet_wrap with argument strip.position = 'left'
  facet_wrap(~ variable, scales = 'free_y', ncol = 1, strip.position = 'left')
 

Мой результирующий график