Данные
Прежде всего, пожалуйста, прочитайте , как сделать воспроизводимый пример : dput(your_data)
- лучший способ сделать ваши данные доступными для всех, кто пытается вам помочь.
dat <- read.table(
text = " yearinitiated midaction cyberattacks
1995 81 NA
1996 75 NA
1997 81 NA
1998 264 NA
1999 363 NA
2000 98 1
2001 105 7
2002 83 NA
2003 79 3
2004 52 2
2005 50 4
2006 35 8
2007 26 18
2008 39 27
2009 31 28
2010 73 15
2011 NA 27",
stringsAsFactors = F,
header = T
)
Почему grid.arrange()
не работает?
Если вы обратитесь к справочным страницам, вы увидите, что функция gridExtra::grid.arrange()
предназначена для:
Настройте макет gtable для размещения нескольких страниц на странице
Где grob
обозначает графический объект . Очень важно, чтобы эта функция работала с:
... объектами grobs, gtables, ggplot или trellis ...
И именно поэтому, когда вы выводите свои данныеиспользование base::plot()
с использованием gridExtra::grid.arrange()
не лучшая идея. Проверьте класс ваших plot1
и plot2
переменных:
class(plot1)
#"NULL"
class(plot2)
#"NULL"
Приведенный выше вывод говорит вам, что plot()
вызовы из вашего кода возвращают NULL
, а график, который вы видите на своем графическом устройствеесть только побочный эффект из base::plot()
. Функция не возвращает графический объект , который вы можете в дальнейшем использовать в своем коде. Вы можете узнать больше о побочных эффектах и нечистых функциях здесь .
Почему вам не нужны grid.arrange()
?
Вам это не нужно, потому что есть другие инструменты, которые вы можете использовать для своих целей.
Печать с base::plot()
Если вы прочитали страницу справки для функции base::par()
, вынайдет описание mfrow, mfcol , параметры par()
:
Вектор вида c (nr, nc). Последующие рисунки будут отображаться в массиве nr-by-nc на устройстве столбцами (mfcol) или строками (mfrow) соответственно.
Это означает, что если вы хотите построить график Cyber Attacksвыше графика MID, вы должны позвонить par()
, прежде чем строить таким образом:
par(
mfrow = c(2, 1),
bty = 'n', # suppress the box around the plot
col = '#000F55', # set color of the plot
col.axis = 'grey25', # make axes grey,
col.lab = 'grey25', # make labels grey
col.main = 'grey25', # make main text grey
family = 'mono', # set font family
mar = rep(2, 4), # set margins
tcl = -0.25, # set ticks length
xaxs = 'r', # apply axis style
yaxs = 'r' # same as above
)
Настройка ограничений по x:
XLIM <- range(dat$yearinitiated, na.rm = T)
После этого вы можете назвать свои графики следующим образом:
# Cyber attacks
plot(x = dat$yearinitiated,
y = dat$cyberattacks,
xlim = XLIM,
xlab = "Year",
ylab = "# of Cyber Attacks",
main = "Cyber Attacks over Time",
type = "l"
)
# MID attacks
plot(x = dat$yearinitiated,
y = dat$midaction,
xlim = XLIM,
xlab = "Year",
ylab = "# of MIDs",
main = "MIDs Attacks over Time",
type = "l"
)
# dev.off()
Что дает вам следующий график:
Чтобы сбросить настройки par
, позвоните dev.off()
.
Построение с помощью ggplot2
Вы можете использовать facet_wrap()/facet_grid()
, как это предлагается @ dc37.
Зачем вам два участка?
ЧестноЯ думаю, что нет. Гораздо проще сравнивать две тенденции на одном графике, чем пытаться сравнивать два набора данных, представленных отдельными графиками.
Использование функциональности base
:
Используя функции base::plot()
, base::lines()
и base::legend()
, вы можете легко наносить одновременно атаки MID и Cyber на одном графике:
# Plot MID attacks
plot(x = dat$yearinitiated,
y = dat$midaction,
xlim = XLIM,
ylim = range(dat[, -1], na.rm = T),
col = "skyblue",
xlab = "Year",
ylab = "Count",
main = "Cyber Attacks vs Military actions over Time",
type = "s"
)
# Add Cyber attacks
lines(
x = dat$yearinitiated,
y = dat$cyberattacks,
col = "red",
type = 's'
)
# Add legend
legend(
x = max(dat$yearinitiated, na.rm = T) - 5.5,
y = max(dat[, -1], na.rm = T),
legend = c('Cyber Attacks', 'Military actions'),
fill = c('red', 'skyblue')
)
Или, в качестве альтернативы функциональности base
, вы можете просто использовать ggplot2
и несколько функций из пакетов tidyverse
:
library(tidyverse)
dat %>%
gather(key = 'Action', value = 'Count', -yearinitiated) %>%
rename('Year' = yearinitiated) %>%
ggplot(aes(x = Year, y = Count, color = Action)) +
geom_step() +
ggthemes::theme_few() +
ggtitle('Military actions vs Cyber attacks')