Превратите кадр данных дат в матрицу симметрии разницы во времени в R

У меня есть датафрейм букв и дат:

Dates <- data.frame(X = c("A", "B", "C", "D"), Y = c("1/1/1988","1/1/2000","11/1/1996", "2/1/1990"))
Dates$Y <- as.Date(Dates$Y, "%m/%d/%Y")

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

Output <- matrix(c(0, 12.01, 8.84, 12.01, 0, 3.17, 8.84, 3.17, 0), nrow=3, ncol=3,
            dimnames = list(c("A", "B", "C"),
                            c("A", "B", "C")))

Огромное спасибо заранее!


person user9351962    schedule 24.04.2018    source источник
comment
У вас есть A, B, C и D в вашем Dates, тогда как в вашем Output только A, B и C.   -  person Ronak Shah    schedule 24.04.2018


Ответы (1)


Мы можем использовать outer вместе с нашей пользовательской функцией для вычисления разницы дат в годах.

outer(Dates$Y, Dates$Y, FUN = function(x,y) 
     round(abs(as.numeric(difftime(x, y, unit="weeks"))/52.25), 2))

#      [,1]  [,2] [,3] [,4]
#[1,]  0.00 11.98 8.82 2.08
#[2,] 11.98  0.00 3.16 9.90
#[3,]  8.82  3.16 0.00 6.74
#[4,]  2.08  9.90 6.74 0.00

Код для расчета разницы дат в годах взят из здесь .


Как упоминал @thelatemail в комментариях, было бы более эффективно (а также аккуратно), если бы мы удалили функции abs, деления и round вне outer

abs(outer(Dates$Y, Dates$Y, difftime, units="weeks") / 52.25)
person Ronak Shah    schedule 24.04.2018
comment
Вероятно, более эффективно выполнять abs/division вне вызова outer, если у вас уже есть матрица - например, abs(outer(Dates$Y, Dates$Y, difftime, units="weeks") / 52.25). Также устраняет необходимость в анонимной функции. - person thelatemail; 24.04.2018
comment
@RonakShah это фантастика! Большое спасибо! Это очень полезно. - person user9351962; 24.04.2018