R - обнаружение разницы во времени [дубликат]

У вас есть объект с вашими значениями по умолчанию, но этот объект тоже является аргументом, поэтому для первого аргумента нужен пустой объект, являющийся объектом с заполненными значениями.

function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) {
}

То, что в псевдокоде будет:

function drawES6Chart({**first argument**} = {**default value for first argument**}) {
}
51
задан jogo 8 January 2016 в 22:25
поделиться

8 ответов

В списке рассылки R-Help есть сообщение точно так же, как и ваше (ранее я упоминал список CRAN).

Здесь ссылка . Существует два предложенных решения:

  • В среднем 365,25 / 12 дней в месяц, поэтому следующее выражение дает количество месяцев между d1 и d2:
< blockquote>
#test data 
d1 <- as.Date("01 March 1950", "%d %B %Y")    
d2 <- as.Date(c("01 April 1955", "01 July 1980"), "%d %B %Y")
# calculation 
round((d2 - d1)/(365.25/12))
  • Другая возможность состоит в том, чтобы получить длину seq.Dates следующим образом:
as.Date.numeric <- function(x) structure(floor(x+.001), class = "Date")
sapply(d2, function(d2) length(seq(d1, as.Date(d2), by = "month")))-1
43
ответ дан Dirk Eddelbuettel 18 August 2018 в 00:37
поделиться
  • 1
    Спасибо, Дирк. Это умный трюк. Говоря об элементах, я узнал, что это также работает. & Gt; as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'weeks' ) & gt; as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'days'), но он останавливается и на «неделе». – knguyen 4 January 2010 в 01:18
  • 2
    Я думаю, что это просто умная перегрузка оператора - для вызова той же функции difftime(). & quot; Без свободного обеда & quot; Как говорится :) – Dirk Eddelbuettel 4 January 2010 в 01:28
  • 3
    Я нашел это очень медленным для больших наборов данных. Ответ Маноэля Галдино ниже намного быстрее. – anotherfred 13 April 2018 в 10:41
  • 4
    Это намного быстрее, чем принятый ответ. – anotherfred 13 April 2018 в 10:41
  • 5
    @anotherfred И потенциально ложно. Быстрый пример - это даты 2017-01-31 и 2018-03-01. Дает «13» здесь с его первым ответом (как только мы добавим недостающие as.numeric() и «12» со вторым ответом. Мой ответ дает «14», как хотелось бы. – Dirk Eddelbuettel 13 April 2018 в 12:52
  • 6
    @DirkEddelbuettel извините, должен был уточнить - я имел в виду, что его первый метод полезен для таких случаев, как мой, где у меня есть большой набор данных, но все даты - 1-е число месяца. – anotherfred 16 April 2018 в 09:20
  • 7
    Предполагается, что у всех дат есть целых несколько месяцев между ними, но полезно. – anotherfred 16 April 2018 в 09:21
43
ответ дан Dirk Eddelbuettel 6 September 2018 в 16:16
поделиться
47
ответ дан Dirk Eddelbuettel 29 October 2018 в 22:27
поделиться

Может быть более простой способ. Это не функция, но это только одна строка.

length(seq(from=date1, to=date2, by='month')) - 1

, например

> length(seq(from=Sys.Date(), to=as.Date("2020-12-31"), by='month')) - 1

Производит:

[1] 69

Это вычисляет количество целых месяцев между двумя датами. Удалите -1, если вы хотите включить текущий месяц / остаток, который не является целым месяцем.

28
ответ дан Dominic 18 August 2018 в 00:37
поделиться
  • 1
    Это не всегда дает ожидаемые результаты. length(seq(from=as.Date("2015-01-31"), to=as.Date("2015-03-31"), by='month')) = 3 Кроме того, length(seq(from=as.Date("2015-01-31"), to=as.Date("2015-04-30"), by='month')) = 3 – Octave1 18 August 2017 в 12:57
library(lubridate)

case1: наивная функция

mos<-function (begin, end) {
      mos1<-as.period(interval(ymd(begin),ymd(end)))
      mos<-mos1@year*12+mos1@month
      mos
}

case2: если вам нужно учитывать только «месяц», независимо от «дня»

mob<-function (begin, end) {
      begin<-paste(substr(begin,1,6),"01",sep="")
      end<-paste(substr(end,1,6),"01",sep="")
      mob1<-as.period(interval(ymd(begin),ymd(end)))
      mob<-mob1@year*12+mob1@month
      mob
}

Пример:

mos(20150101,20150228) # 1
mos(20150131,20150228) # 0
# you can use "20150101" instead of 20150101

mob(20150131,20150228) # 1
mob(20150131,20150228) # 1
# you can use a format of "20150101", 20150101, 201501
5
ответ дан hyunwoo jeong 18 August 2018 в 00:37
поделиться
  • 1
    интервал (mdy (20150101), mdy (20150228))% /% месяцев (1) Просто используйте собственный функциональный интервал lubridate. – mtelesha 19 September 2017 в 17:35
  • 2
    спасибо мтелэша. Однако, в моем бизнесе, мне нужно рассчитать «месячный счет» 2 дня. Например, месяцы между 20150131 и 20150201 должны быть 1. Таким образом, я использовал функцию «mob» для пользователя. Вы знаете, как сделать это с помощью lubridate? – hyunwoo jeong 26 September 2017 в 06:08
  • 3
    Я думаю, вы могли бы использовать месяц (ymd) - месяц (ymd). Или вы можете сделать три столбца один на год, месяц и день. – mtelesha 26 September 2017 в 22:53
  • 4
    Конечно, но в случае другого года это не сработает. Например, месяц (ymd (20170101)) - месяц (ymd (20161231)) = -11 нет 1 – hyunwoo jeong 11 October 2017 в 00:39
library(lubridate)
date1 = "1 April 1977"
date2 = "7 July 2017"

date1 = dmy(date1)
date2 = dmy(date2)
number_of_months = (year(date1) - year(date2)) * 12 + month(date1) - month(date2)

Разница в месяцах = 12 * разница в годах + разница в месяцах.

Следующее может потребоваться исправить с помощью условия ifelse для вычитания месяца

3
ответ дан mrsrinivas 18 August 2018 в 00:37
поделиться

Я думаю, что это более близкий ответ на вопрос, заданный с точки зрения соотношения с функцией MathWorks

Функция месяцев MathWorks

MyMonths = months(StartDate, EndDate, EndMonthFlag)

Мой R-код

library(lubridate)
interval(mdy(10012015), today()) %/% months(1)

Вывод (например, когда код был запущен в апреле 2016 года)

[1] 6

Lubridate [package] предоставляет инструменты, облегчающие синтаксический анализ и управление датами. Эти инструменты сгруппированы по общей цели. Более подробную информацию о каждой функции можно найти в ее справочной документации.

interval {lubridate} создает объект Interval-class с указанными датами начала и окончания. Если дата начала происходит до даты окончания, интервал будет положительным. В противном случае это будет отрицательно

сегодня. {Lubridate} Текущая дата

months {Base} Извлечение месяца. Это общие функции: методы для внутренних классов даты и времени документируются здесь.

% /% {base} указывает целочисленное деление AKA (x% /% y) (с точностью до округления)

21
ответ дан mtelesha 18 August 2018 в 00:37
поделиться

Простая функция ...

elapsed_months <- function(end_date, start_date) {
    ed <- as.POSIXlt(end_date)
    sd <- as.POSIXlt(start_date)
    12 * (ed$year - sd$year) + (ed$mon - sd$mon)
}

Пример ...

>Sys.time()
[1] "2014-10-29 15:45:44 CDT"
>elapsed_months(Sys.time(), as.Date("2012-07-15"))
[1] 27
>elapsed_months("2002-06-30", c("2002-03-31", "2002-04-30", "2002-05-31"))
[1] 3 2 1

Для меня имеет смысл подумать об этой проблеме, просто вычитая две даты и поскольку minuend − subtrahend = difference (wikipedia) , я поставил более позднюю дату в списке параметров.

Обратите внимание, что он отлично работает для дат, предшествующих 1900 году, несмотря на те даты, которые имеют внутренние представления года как отрицательный, благодаря правилам вычитания отрицательных чисел ...

> elapsed_months("1791-01-10", "1776-07-01")
[1] 174
35
ответ дан pbnelson 18 August 2018 в 00:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: