Считаем дни года с високосными годами

В настоящее время я пытаюсь закодировать это в R. Я хотел бы взять дату, которая у меня есть в формате %Y-%m-%d (например, 2017-12-31), и преобразовать ее в день года. Однако я бы хотел, чтобы 28 февраля всегда считались днем ​​№ 59, а 01 марта - днем ​​№ 61. Когда это не високосный год, он просто пропускает №60. Таким образом, 01.01 всегда # 1, а 31.12 всегда # 366.

Я уже пробовал использовать strftime() и yday(), но оба они не пропускают 60-й день в високосный год. 31 декабря будет день № 365 или № 366, в зависимости от того, високосный год это или нет.

Если у кого-нибудь есть представление о том, как я могу написать это на R, это было бы здорово! Большое спасибо.

file <- read.table("PATHTOMYFILE", fill = TRUE, header = TRUE)
file <- file[-c(1), ]
file$datetime <- as.Date(as.character(file$datetime))
file <- file[which(file$datetime <= as.Date("2017-09-30")), ]
file$x <- file[, 4]
file$x <- as.numeric(as.character(file$x))

# Year-day function
yearday <- function(d){
# Count previous months
yd <- ifelse(lubridate::month(d) > 1, sum(lubridate::days_in_month(1: 
(lubridate::month(d)-1))), 0)

# Add days so far in month & extra day if after February
yd <- yd + lubridate::day(d) + ifelse(lubridate::month(d)>2, 1, 0)
yd
}

file$Day <- yearday(as.Date((file$datetime), format = "%Y-%m-%d"))

person Sarah    schedule 01.03.2019    source источник


Ответы (3)


Вы можете использовать функцию lubridate leap_year. Например.,

> library(lubridate)
> 
> dates <- c(as.Date("2017-12-31"), as.Date("2016-12-31"))
> 
> y <- as.Date("2016-12-31")
> z <- as.Date("2017-12-31")
> 
> leap_every_year <- function(x) {
+   
+   ifelse(yday(x) > 59 & leap_year(x) == FALSE, yday(x) + 1, yday(x))
+   
+ }
> 
> leap_every_year(y)
[1] 366
> leap_every_year(z)
[1] 366
> leap_every_year(dates)
[1] 366 366

РЕДАКТИРОВАТЬ: увидел, что это очень похоже на решение @ MDEWITT, но вместо этого использует lubridate. Хотя идеи похожие. Удачи!

person Andrew    schedule 01.03.2019
comment
Рад, что это помогло! - person Andrew; 01.03.2019

Один из вариантов - использовать эту функцию:

Как учитывать високосные годы?

leap_year <- function(year) {
  return(ifelse((year %%4 == 0 & year %%100 != 0) | year %%400 == 0, TRUE, FALSE))
}

Затем напишите код, который управляет номером дня, который у вас есть, на основе ваших правил (например, в високосном году

 if(leap_year(mydate)== TRUE & day_num>60) {
 day_num + 1} else{
  day_num}
person MDEWITT    schedule 01.03.2019

Вот функция, которая выполняет свою работу. Он суммирует все месяцы до текущего месяца, добавляет дни для текущего месяца, а затем добавляет високосный день, если месяц после февраля.

# Year-day function
yearday <- function(d){
  # Count previous months
  yd <- ifelse(lubridate::month(d) > 1, sum(lubridate::days_in_month(1:(lubridate::month(d)-1))), 0)
  # Add days so far in month & extra day if after February
  yd <- yd + lubridate::day(d) + ifelse(lubridate::month(d)>2, 1, 0)
  yd
}

# Test function
yearday(as.Date("2017-12-31", format = "%Y-%m-%d"))
#> [1] 366
yearday(as.Date("2017-03-01", format = "%Y-%m-%d"))
#> [1] 61
yearday(as.Date("2017-01-01", format = "%Y-%m-%d"))
#> [1] 1

Создано 01.03.2019 с помощью пакета REPEX (v0.2.1)

person Lyngbakr    schedule 01.03.2019
comment
Я получаю это предупреждающее сообщение, когда запускаю ваш код. Предупреждающее сообщение: В 1: (lubridate :: month (d) - 1): числовое выражение содержит 29220 элементов: только первая использованная дата начала - 1937-10-01, и подсчет верен, пока не дойдет до 1937-11- 01 и снова запускается в день # 275. - person Sarah; 01.03.2019
comment
@SamanthaSullivan Можете ли вы отредактировать свой вопрос, включив в него данные и точный код, который вы используете, чтобы я мог воспроизвести проблему? - person Lyngbakr; 01.03.2019
comment
Я добавил код. Я не знаю, как добавить таблицу. Он просто начинается с таблицы с 5 заголовками. Третий заголовок называется datetime, где даты находятся в формате $ Y-% m-% d, а затем я добавляю 6-й столбец с именем x, который является просто переименованием моего 4-го столбца, который является моим значением данных, по которым я выполняю анализ. Как мне добавить свои данные? - person Sarah; 01.03.2019
comment
@SamanthaSullivan Проще всего добавить данные, используя dput или dump и скопировав и вставив вывод. Например, dump("file", ""), если ваш фрейм данных называется file. - person Lyngbakr; 01.03.2019