У меня есть ежедневные данные об осадках за 43 года. Данные представлены в формате ДД/ММ/ГГГГ. Дата начала 01.01.1978, дата окончания 31.12.2020. Я хочу изменить/переставить эти данные в таблицу (365 (строк - количество дней в году) x 43 (столбцы - годы записи данных)) так, чтобы первый день каждого года данных начинался 1 апреля и заканчивался 31 марта следующего года (например, данные 1978-1979 года начинаются с 04.01.1978 и заканчиваются 31.03.1979).
Ожидаемый формат таблицы:
Как написать код R для этого? Я новичок в Р.
Решение проблемы
cumsum
Вы можете просто разделить данные об осадках на '04-01'
. Это дает список S
с 365 или 366 тактами. Просто адаптируйте все `length<-`
под 366, куда NA
добавляется на всякий случай. Наконец, просто cbind
добавьте day
столбец. Имена столбцов для лет можно создать с помощью strftime
.
Сначала нам нужно расширить недостающее начало и конец, т.е. 1 апреля до начала ваших мер и 31 марта после, а merge
это до данных.
aux <- data.frame(
date=seq.Date(as.Date("1977-04-01"), as.Date("1982-03-31"), 'day')
)
dat <- merge(dat, aux, all=TRUE)
Решение 1, больше строк для високосных лет
S <- split(dat$rainfall, cumsum(strftime(dat$date, '%m-%d') == '04-01'))
yrs <- unique(strftime(dat$date, '%Y'))
yrs <- apply(cbind(yrs[-length(yrs)], yrs[-1]), 1, \(x)
paste(x[[1]], substr(x[[2]], 3, 4), sep='_'))
res1 <- cbind(day=1:366, setNames(do.call(cbind.data.frame, lapply(S, `length<-`, 366)),
yrs))
Дает:
tail(res1)
# day 1977_78 1978_79 1979_80 1980_81 1981_82
# 361 361 81.199690 110.382115 75.45856 134.532854 NA
# 362 362 1.713985 5.091447 13.14269 7.704723 NA
# 363 363 1.724329 37.100737 96.13059 42.934299 NA
# 364 364 113.334633 20.346748 97.99042 73.300045 NA
# 365 365 102.177311 30.465944 341.11990 133.788648 NA
# 366 366 NA NA 235.38249 NA NA
Решение 2, все строки 366
Если мы хотим, чтобы дни были выровнены по годам, мы могли бы append
использовать NA
последующий день 334
в невисокосных годах.
r <- by(dat, cumsum(strftime(dat$date, '%m-%d') == '04-01'), \(x) {
rf <- x$rainfall
yrs <- unique(strftime(x$date, '%Y'))
yrs <- paste(yrs[1], substr(yrs[2], 3, 4), sep='_')
if (length(rf)!= 366) {
rf <- append(rf, NA, 334)
}
`attr<-`(rf, 'yrs', yrs)
})
res2 <- cbind(day=1:366, setNames(do.call(cbind.data.frame, r), sapply(r, attr, 'yrs')))
Дает
res2[331:337, ]
# day 1977_78 1978_79 1979_80 1980_81 1981_82
# 331 331 47.65507 99.59559 38.80979 126.29785 NA
# 332 332 87.92888 125.35296 46.02958 82.03465 NA
# 333 333 28.98329 29.83954 31.30135 87.30667 NA
# 334 334 279.30901 39.37710 12.03988 283.37096 NA
# 335 335 NA NA 206.63815 NA NA
# 336 336 48.48830 108.82812 45.95315 36.61144 NA
# 337 337 16.72346 25.30704 36.15601 210.51755 NA
Данные:
dat <- data.frame(
date=seq.Date(as.Date('1978-01-01'), as.Date('1981-12-31'), 'day')
)
set.seed(42)
dat$rainfall <- rnorm(nrow(dat), 20, 100) |> abs()
Комментариев нет:
Отправить комментарий