Создать цикл for в широком формате R ggplot

Я пытаюсь решить две проблемы, чтобы создать один полный график (желательно в ggplot). Во-первых, я думаю, что мне нужно разработать цикл for для данных в широком формате, чтобы я мог отображать несколько рядов в виде отдельных линий на одном графике.

Во-вторых, мне нужно построить еще один столбец (климатические данные, разные значения y) поверх отдельных рядов. Я знаю, что есть много споров по поводу двухосевых графиков, но клиент запросил именно этот график, и я не могу обойти его.

Это идеальный график для построения (позаимствовано из публикации 2011 года) введите здесь описание изображения

Мои данные в настоящее время в широком формате, и я думаю создать цикл for для столбцов 2:13, чтобы создавать отдельные серые линии для каждой серии. Затем я хотел бы иметь возможность выборочно добавлять определенный месяц (столбцы 14:25) красным сверху. Я с удовольствием переключусь на длинный формат, если смогу выборочно вытащить месяцы и нанести их на серые ряды данных. Ниже приведено небольшое подмножество данных, фактический набор данных намного больше.

WideDF <- structure(list(Year = c("2008", "2009", "2010", "2011", "2012", 
"2013", "2014"), M3T1045 = c(153.821659726048, 123.081558884975, 
176.771512423309, 181.76302562778, 121.366484915564, 112.166318263156, 
83.430179685548), M3T2045 = c(1979.67428393397, 2304.69652323779, 
2038.57278760525, 1598.21780623635, 1698.10896695776, 1282.44883906715, 
1243.48492202174), M3T3045 = c(2059.61060104009, 2538.3591621577, 
2836.19881815023, 2529.3912848661, 2715.04505989801, 2137.18245498415, 
1914.61513277697), M3T4045 = c(3923.28951818649, 4180.76535402238, 
4214.78156108969, 4295.05332803458, 4522.22790268241, 4472.36745319943, 
4098.5309021999), M3T5045 = c(2018.8160905218, 1997.65271391178, 
2079.82809750919, 2248.83387563616, 2494.15706661903, 1355.10547024274, 
1353.37214047842), M3T6045 = c(4409.16623051298, 4276.51428713093, 
3831.60326756482, 3308.15549785341, 4045.82249844548, 4462.00875828256, 
3572.81219768132), M3U1045 = c(113.83650201514, 118.780241020127, 
114.984700722952, 133.421492210513, 205.600098647934, 122.476010617811, 
97.1844650220458), M3U2045 = c(337.787032910181, 376.487106438174, 
430.035628616836, 414.099557447903, 458.763256619945, 331.056861800248, 
238.741139683364), M3U3045 = c(320.507421943828, 322.708996668388, 
313.17219893837, 270.058319678974, 376.456328254947, 267.987391226506, 
296.912173018184), M3U4045 = c(1095.26781018262, 1138.4400696583, 
1401.22300738868, 1387.70010663431, 1658.03042540523, 1230.4459207838, 
987.787227627777), M3U5045 = c(125.346087984721, 127.324176091091, 
111.68607241898, 164.421987100271, 241.013673561191, 158.550165076745, 
157.942524508873), M3U6045 = c(774.63712785103, 824.750682887739, 
745.467515460673, 666.817790501942, 988.567171986328, 654.042598223899, 
559.472739395766), Jan = c(1.11, 3.38, 3.41, 1.26, 1.02, -1.39, 
1.71), Feb = c(2.32, 2.85, 3.09, 0.97, -1.52, -1.22, 1.55), Mar = c(2.47, 
2.1, 3.59, 1.31, -2.29, -1.62, 1.7), Apr = c(2.45, 2, 2.5, 1.96, 
-1.93, -2.14, 1.45), May = c(1.44, 1.97, 1.47, 2.12, -1.26, -1.35, 
1.48), Jun = c(1.77, 3.53, 1.86, 1.74, 2.06, 1.57, 1.73), Jul = c(2.07, 
4.66, 1.14, 1.1, 1.07, 2.28, 3.09), Aug = c(2.83, 4.74, -1.6, 
2.55, 1.08, 2.79, 3.05), Sep = c(4.04, 3.63, -1.22, 2.26, 1.5, 
3.48, 1.92), Oct = c(3.89, 4.21, 0.97, 2.7, 2.46, 2.31, 2.53), 
    Nov = c(4.09, 3.97, 1.28, 1.67, 1.12, 2.13, 2.16), Dec = c(4.21, 
    3.79, 2.05, 1.38, 1.51, 1.84, 2.71)), .Names = c("Year", 
"M3T1045", "M3T2045", "M3T3045", "M3T4045", "M3T5045", "M3T6045", 
"M3U1045", "M3U2045", "M3U3045", "M3U4045", "M3U5045", "M3U6045", 
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 
"Oct", "Nov", "Dec"), row.names = 65:71, class = "data.frame")

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

Я также пытался использовать цикл for, предоставленный Didzis здесь, но продолжал получать ошибку, что каждая группа состоит только из 1 наблюдения. Это код, который я пытался использовать:

plotAllLayers(WideDF)
fields <- names(WideDF[,1:13])
p <- ggplot(aes(x=Year), data=WideDF)
for (i in 2:length(fields)) {
loop_input = paste("geom_smooth(aes(y=",fields[i],",color='",fields[i],"'))", sep="")
p <- p + eval(parse(text=loop_input))
}
p <- p + guides( color = guide_legend(title = "",) )
p

Любая помощь будет оценена по решению этой проблемы.


person KKL234    schedule 19.06.2017    source источник
comment
Почему вы настаиваете на сохранении ваших данных в широком формате? Почему бы не изменить форму на длинный/высокий формат, чтобы упростить построение графика.   -  person MrFlick    schedule 19.06.2017
comment
Как я уже упоминал в посте, я буду рад изменить форму на длинную, если есть способ вытащить климатические данные за определенные месяцы для построения сверху. Когда я первоначально преобразовал в длинный формат, он отображал все мои данные (отдельные временные ряды, а также климатические данные в месяцах). Если есть способ избежать этого и по-прежнему создавать приведенный выше график, я буду рад перейти на лонг.   -  person KKL234    schedule 19.06.2017
comment
Я бы не рекомендовал отображать два ряда данных с разными единицами измерения на одном графике, особенно если масштабирование выполняется произвольно. Это имеет тенденцию подразумевать отношения, которые не соответствуют действительности.   -  person AkselA    schedule 19.06.2017


Ответы (1)


Ваши данные в беспорядке, вы не можете использовать свою переменную M3T или M3U. Кроме того, вам обязательно следует переключиться на длинный формат и избегать циклов в ggplot2.

Вот пример того, как это сделать:

library(tidyverse)

coef_shrink <- 120
month_picked <- month.abb[1]

# convert to long format:
longdf <- WideDF %>%
  gather(key = var, value = measure
         , -Year)

# limit to the monthly variables:
longdf_year <- longdf %>%
  filter(var %in% month_picked) %>%
  mutate(measure = measure * coef_shrink)

# limit to the M* variables
longdf_MTU <- longdf %>%
  filter(!var %in% month.abb)

# plot:
ggplot(longdf_MTU, aes(x = Year, y = measure, group = var)) +
  geom_line() +
  geom_line(data = longdf_year, aes(x = Year, y = measure), color = "red")+
  scale_y_continuous(
    "var 1",
    sec.axis = sec_axis(~ . / coef_shrink, name = "var 2")
  )

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

person YCR    schedule 19.06.2017
comment
Спасибо за возможный ответ. Можете ли вы помочь объяснить свой ответ немного больше? Чтобы уточнить, я объединил 2 отдельных кадра данных вместе, чтобы попытаться скомпилировать все свои данные по годам (столбцы df1 = M3U и M3T, df2 = столбцы месяца). Если я смогу разделить их и наложить 2 графика, я буду рад это сделать. Кроме того, почему я не могу использовать свои переменные M3U и M3T? Это мои основные данные, которые я хотел бы использовать для создания отдельных линий на графике. Месяцы (январь-декабрь) есть, поэтому я могу выборочно выбирать месяцы для наложения на данные M3U и M3T. - person KKL234; 19.06.2017
comment
ggplot2 предоставляет возможность отображать ваши данные практически любым удобным для вас способом, начиная с того момента, когда они представлены в длинном формате, и использовать стек слоев для создания графика. Таким образом, вы можете объединить несколько графиков ggplot, если хотите. По сути, в вашем случае нет причин объединять ваши файлы df. - person YCR; 19.06.2017
comment
Кроме того, вы можете добавить вторую ось: другая-y-ось-справа" title="график с двумя осями y, одна ось y слева и другая ось y справа"> stackoverflow.com/questions/3099219/ - person YCR; 19.06.2017
comment
Я просмотрел вопрос о stackoverflow, который вы опубликовали ранее, но каждый раз застревал на нем. Если я помещу свои данные в длинный формат, как я могу построить только определенные переменные (данные M3U и M3T), не отображая другие переменные, которые будут присутствовать (январь-декабрь)? - person KKL234; 19.06.2017
comment
Отредактировал ответ со 2-й осью - person YCR; 19.06.2017