#r #date #time-series #tidyr
#r #Дата #временные ряды #tidyr
Вопрос:
У меня есть таблица с данными из датчика потока, упорядоченная следующим образом:
Water.Year May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr
1 1953-1954 55.55 43.62 30.46 26.17 26.76 41.74 19.92 41.25 28.77 20.96 12.47 10.51
2 1954-1955 23.49 81.35 46.71 29.33 67.83 133.30 37.62 30.16 21.07 19.38 13.87 10.63
3 1955-1956 9.87 51.59 55.36 63.03 154.08 98.15 104.06 32.85 22.89 17.30 15.68 10.88
> data <- structure(list(Water.Year = structure(1:6, .Label = c("1953-1954", "1954-1955", "1955-1956", "1956-1957", "1957-1958", "1958-1959", "1959-1960", "1960-1961", "1961-1962", "1962-1963", "1963-1964", "1964-1965", "1965-1966", "1966-1967", "1967-1968", "1968-1969", "1969-1970", "1970-1971", "1971-1972", "1972-1973", "1973-1974", "1974-1975", "1975-1976", "1976-1977", "1977-1978", "1978-1979", "1979-1980", "1980-1981", "1981-1982", "1982-1983", "1983-1984", "1984-1985", "1985-1986", "1986-1987", "1987-1988", "1988-1989", "1989-1990", "1990-1991", "1991-1992", "1992-1993", "1993-1994", "1994-1995", "1995-1996", "1996-1997", "1997-1998", "1998-1999", "1999-2000", "2000-2001"), class = "factor"), May = c(55.55, 23.49, 9.87, 18.03, 17.46, 11.37), Jun = c(43.62, 81.35, 51.59, 28.61, 15.14, 29.48), Jul = c(30.46, 46.71, 55.36, 24.36, 20.09, 19.48), Ago = c(26.17, 29.33, 63.03, 22.01, 16.97, 16.86), Set = c(26.76, 67.83, 154.08, 28.51, 27.24, 21.01), Oct = c(41.74, 133.3, 98.15, 53.72, 35.78, 19.78), Nov = c(19.92, 37.62, 104.06, 115.78, 20.35, 18.69), Dic = c(41.25, 30.16, 32.85, 32.04, 22, 18.86), Ene = c(28.77, 21.07, 22.89, 25.44, 13.27, 14.89), Feb = c(20.96, 19.38, 17.3, 14.53, 10.37, 10.4), Mar = c(12.47, 13.87, 15.68, 10.78, 8.77, 8.79), Abr = c(10.51, 10.63, 10.88, 9.33, 7.69, 8.99)), .Names = c("Water.Year", "May", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Dic", "Ene", "Feb", "Mar", "Abr"), row.names = c(NA, 6L), class = "data.frame")
Данные упорядочены по «водным годам», где каждый год начинается в мае и заканчивается в апреле следующего года (это можно увидеть в первом столбце).
Я хочу преобразовать его во фрейм данных с тремя столбцами: Календарь.Год — Месяц — Расход.Измерение
Я уже разобрал воду.Столбец Year разделить на два столбца, используя «отделить» от tidyr:
> df = separate(data, Water.Year, c("year1","year2"))
year1 year2 May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr
1 1953 1954 55.55 43.62 30.46 26.17 26.76 41.74 19.92 41.25 28.77 20.96 12.47 10.51
2 1954 1955 23.49 81.35 46.71 29.33 67.83 133.30 37.62 30.16 21.07 19.38 13.87 10.63
Теперь я планирую использовать «сбор» из tidyr для выполнения остальной части преобразования, но я застрял на том, как я могу создать календарь.Столбец Year, используя год1 для столбцов с мая по декабрь и год2 для января по апрель.
Любая помощь будет оценена.
Комментарии:
1. Пожалуйста, используйте
dput(data)
для публикации воспроизводимого вопроса. Не существует хорошего способа скопировать предоставленные вами данные в том виде, в каком они представлены, без их ввода вручную.2.
library(reshape2); melt(df)
Ответ №1:
Еще одна идея (используя @useR data с английскими месяцами)
library(dplyr)
library(tidyr)
df %>%
separate(Water.Year, c("Year1", "Year2")) %>%
gather(Month, Value, -(Year1:Year2)) %>%
group_by(Year1, Year2) %>%
mutate(Year = if_else(match(Month, month.abb) >= 5, Year1, Year2),
Month = factor(Month, levels = month.abb)) %>%
ungroup() %>%
select(Year, Month, Value) %>%
arrange(Year, Month)
Мы разделяем Water.Year
столбец на Year1
и Year2
и преобразуем данные в длинный формат с помощью gather()
. Затем для каждой группы мы используем match()
и month.abb
, чтобы проверить, больше или равен месяц 5 (май), и присвоить соответствующий год с помощью if_else()
. Наконец, мы удаляем ненужные столбцы и arrange()
by Year
и Month
## A tibble: 36 × 3
# Year Month Value
# <chr> <fctr> <dbl>
#1 1953 May 55.55
#2 1953 Jun 43.62
#3 1953 Jul 30.46
#4 1953 Aug 26.17
#5 1953 Sep 26.76
#6 1953 Oct 41.74
#7 1953 Nov 19.92
#8 1953 Dec 41.25
#9 1954 Jan 28.77
#10 1954 Feb 20.96
## ... with 26 more rows
Комментарии:
1. Отличное решение с использованием
dplyr
! Но порядок ваших окончательных данных немного нарушен, поскольку за вашим «Декабрь 1953» не следует «январь 1954». Посмотрите на мое решение.2. @useR О, точно! Добавлена
factor()
часть. Спасибо!
Ответ №2:
Хорошо, как насчет этого. Это коллапс между reshape и base R.
Я использовал ваш набор данных, как только вы его опубликовали. Спасибо за предоставление.
data <- structure(list(Water.Year = structure(1:6, .Label = c("1953-1954", "1954-1955", "1955-1956", "1956-1957", "1957-1958", "1958-1959", "1959-1960", "1960-1961", "1961-1962", "1962-1963", "1963-1964", "1964-1965", "1965-1966", "1966-1967", "1967-1968", "1968-1969", "1969-1970", "1970-1971", "1971-1972", "1972-1973", "1973-1974", "1974-1975", "1975-1976", "1976-1977", "1977-1978", "1978-1979", "1979-1980", "1980-1981", "1981-1982", "1982-1983", "1983-1984", "1984-1985", "1985-1986", "1986-1987", "1987-1988", "1988-1989", "1989-1990", "1990-1991", "1991-1992", "1992-1993", "1993-1994", "1994-1995", "1995-1996", "1996-1997", "1997-1998", "1998-1999", "1999-2000", "2000-2001"), class = "factor"), May = c(55.55, 23.49, 9.87, 18.03, 17.46, 11.37), Jun = c(43.62, 81.35, 51.59, 28.61, 15.14, 29.48), Jul = c(30.46, 46.71, 55.36, 24.36, 20.09, 19.48), Ago = c(26.17, 29.33, 63.03, 22.01, 16.97, 16.86), Set = c(26.76, 67.83, 154.08, 28.51, 27.24, 21.01), Oct = c(41.74, 133.3, 98.15, 53.72, 35.78, 19.78), Nov = c(19.92, 37.62, 104.06, 115.78, 20.35, 18.69), Dic = c(41.25, 30.16, 32.85, 32.04, 22, 18.86), Ene = c(28.77, 21.07, 22.89, 25.44, 13.27, 14.89), Feb = c(20.96, 19.38, 17.3, 14.53, 10.37, 10.4), Mar = c(12.47, 13.87, 15.68, 10.78, 8.77, 8.79), Abr = c(10.51, 10.63, 10.88, 9.33, 7.69, 8.99)), .Names = c("Water.Year", "May", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Dic", "Ene", "Feb", "Mar", "Abr"), row.names = c(NA, 6L), class = "data.frame")
Я решил использовать информацию о годе, которая была у вас ранее, и просто добавить календарный год на основе этого. Поскольку мы знаем, что май-декабрь — это год 1, а январь-апрель — год 2. Может быть, немного запутанный, но он выполняет свою работу.
df = separate(data, Water.Year, c("year1","year2"))
library(reshape2)
fixDF<-melt(df)
fixDF$CalendarYear<-rep(NA,nrow(fixDF))
fixDF$CalendarYear[min(which(fixDF$variable=="May")):max(which(fixDF$variable=="Dic"))]<-df$year1
fixDF$CalendarYear[min(which(fixDF$variable=="Ene")):max(which(fixDF$variable=="Abr"))]<-df$year2
fixDF<-fixDF[,3:5]
colnames(fixDF)<-c("Month","Flow.Measurement", "Calendar.Year")
Ответ №3:
Хорошо, я только что понял, что месяцы, которые вы указали в structure()
, могут быть на другом языке. Я просто буду придерживаться созданных мной данных, в которых используется английская версия Months. Таким образом, пользователи смогут увидеть соответствующее решение на английском языке.
library(tidyr) # for separate function
library(reshape2) # for melt function
library(dplyr) # for pipe operator and arrange function
# Reproducible Data
weather = structure(list(Water.Year = structure(1:3, .Label = c("1953-1954",
"1954-1955", "1955-1956"), class = "factor"),
May = c(55.55, 23.49, 9.87),
Jun = c(43.62, 81.35, 51.59),
Jul = c(30.46, 46.71, 55.36),
Aug = c(26.17, 29.33, 63.03),
Sep = c(26.76, 67.83, 154.08),
Oct = c(41.74, 133.3, 98.15),
Nov = c(19.92, 37.62, 104.06),
Dec = c(41.25, 30.16, 32.85),
Jan = c(28.77, 21.07, 22.89),
Feb = c(20.96, 19.38, 17.3), Mar = c(12.47, 13.87, 15.68),
Apr = c(10.51, 10.63, 10.88)), .Names = c("Water.Year", "May",
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb",
"Mar", "Apr"), class = "data.frame", row.names = c(NA, -3L))
Кодирование начинается здесь:
df = separate(weather, Water.Year, c("year1","year2"))
# Split into two datasets
columns1 = c("year1", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Dec")
df1 = subset(df, select = c(year1, May:Dec))
df2 = subset(df, select = c(year2, Jan:Apr))
longdf1 = melt(df1, variable.name = "Month", id.vars = "year1",
value.name = "Flow.Measurement")
names(longdf1)[1] = "Calendar.Year"
longdf2 = melt(df2, variable.name = "Month", id.vars = "year2",
value.name = "Flow.Measurement")
names(longdf2)[1] = "Calendar.Year"
# Combine the two datasets
final_df = rbind(longdf1, longdf2)
# Releveling the Month
final_df$Month = factor(final_df$Month, levels = month.abb)
final_df = arrange(final_df, Calendar.Year, Month)
Окончательный фрейм данных:
> final_df
Calendar.Year Month Flow.Measurement
1 1953 May 55.55
2 1953 Jun 43.62
3 1953 Jul 30.46
4 1953 Aug 26.17
5 1953 Sep 26.76
6 1953 Oct 41.74
7 1953 Nov 19.92
8 1953 Dec 41.25
9 1954 Jan 28.77
10 1954 Feb 20.96
11 1954 Mar 12.47
12 1954 Apr 10.51
13 1954 May 23.49
14 1954 Jun 81.35
15 1954 Jul 46.71
16 1954 Aug 29.33
17 1954 Sep 67.83
18 1954 Oct 133.30
19 1954 Nov 37.62
20 1954 Dec 30.16
21 1955 Jan 21.07
22 1955 Feb 19.38
23 1955 Mar 13.87
24 1955 Apr 10.63
25 1955 May 9.87
26 1955 Jun 51.59
27 1955 Jul 55.36
28 1955 Aug 63.03
29 1955 Sep 154.08
30 1955 Oct 98.15
31 1955 Nov 104.06
32 1955 Dec 32.85
33 1956 Jan 22.89
34 1956 Feb 17.30
35 1956 Mar 15.68
36 1956 Apr 10.88
Ответ №4:
Я решил использовать некоторые фрагменты всех ответов, которые я получил. Это код, который я написал:
library(dplyr)
library(tidyr)
#separate the year column into two years
df_years <- df %>%
separate(Water.Year, c("Year1", "Year2"))
#create two different dataframes for each section of the year
df1 <- subset(df_years, select = c(Year1, May:Dec))
df2 <- subset(df_years, select = c(Year2, Jan:Apr))
#rename both years' columns using the same name
colnames(df2)[1] <- "Year"
colnames(df1)[1] <- "Year"
#join both dataframes
cleandata <- full_join(df1, df2, by = "Year")
#sort months chronologically
cleandata <- cleandata[, c("Year", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")]
#convert to tidy data set
cleandata <- gather(cleandata, "Month", "Flow", 2:13)
#sort by year and month
cleandata <- arrange(cleandata, Year, Month)