Dificultad para realizar operaciones aritméticas con fechas en R

Estoy manipulando datos que contienen fechas y estoy teniendo un problema. Esencialmente, deseo calcular una nueva fecha basada en dos fechas existentes y otra variable, para todas las filas en mi marco de datos. Por ejemplo, me gustaría poder restar 10 días desde Date1, o calcular la fecha que está a mitad de camino entre Date1 y Date2, etc. Sin embargo, tengo problemas para entender la asignación de clase al agregar la nueva fecha calculada al marco de datos. Marco de datos de muestra:

#  Uncomment to clear your session...
# rm(list = ls(all = TRUE))
tC <- textConnection("StudyID   Date1   Date2
C0031   2-May-09    12-Jan-10
C0032   7-May-09    30-Apr-10")
data <- read.table(header=TRUE, tC)
close.connection(tC)
rm(tC)

#CONVERTING TO DATES    
data$Date1 <- with(data,as.Date(Date1,format="%d-%b-%y"))
data$Date2 <- with(data,as.Date(Date2,format="%d-%b-%y"))

Ahora aquí es donde comienza mi problema

class(data[1, "Date2"] - 10) # class is "Date". So far so good. 
data[1, "newdate"]  <- (data[1, "Date2"] - 10)
class(data[1, "newdate"]) # class is now "numeric"... 

Y probado

data[1, "newdate"]  <- as.Date(data[1, "Date2"] - 10)
class(data[1, "newdate"]) # doesn't help. Class still "numeric"... 

Simplemente no entendiendo por qué este valor se vuelve numérico cuando se le asigna a los datos

0
¿Has probado data $ newdate <- data $ Date1 - 10 ? Creo que el problema es el reciclaje de un solo valor. Como las columnas deben tener la misma longitud, el valor de fecha singular se recicla para coincidir con el número de filas en su data.frame. Supongo (verifico) que las tiras de reciclaje atribuyen, convirtiendo las fechas en sus formas numéricas.
agregado el autor Simon O'Hanlon, fuente

2 Respuestas

The problem is due to recycling of your vector stripping attributes. As I stated in my comment, use e.g. data$newdate <- data$Date1 - 10 to create the whole column without recycling the vector, thus retaining attributes such as Date. Consider the illustrative toy example below:

# Simple vector with an attribute
x <- 1:3
attributes(x) <- list( att = "some attributes" )
x
#[1] 1 2 3
#attr(,"att")
#[1] "some attributes"

# Simple data.frame with 3 rows
df <- data.frame( a = 1:3 )

#  New column using first element of vector with attributes
df$b <- x[1]

#  It is recycled to correct number of rows and attributes are stripped
str(df$b)
# int [1:3] 1 1 1

#  Without recycling attributes are retained
df$c <- x
str(df$c)
# atomic [1:3] 1 2 3
# - attr(*, "att")= chr "some attributes"

#  But they all look the same...
df
#  a b c
#1 1 1 1
#2 2 1 2
#3 3 1 3

Y a partir de tus datos ...

attributes(data$Date1)
# $class
# [1] "Date"
0
agregado
Gracias por estas dos excelentes respuestas, una práctica y la otra diseccionando el comportamiento subyacente. Muy apreciado y ahora despegado!
agregado el autor marcel, fuente

El problema se debe a la inexistencia de la columna newdate en combinación con la asignación de un único valor:

# create a single value in a new column
data[1, "newdate"]  <- data[1, "Date2"] - 10
class(data[1, "newdate"]) # numeric 

# create the whole column
data[ , "newdate2"] <- data[1, "Date2"] - 10
class(data[1, "newdate2"]) # Date

# create a column of class Date before assigning value
data[ , "newdate3"] <- as.Date(NA)
data[1, "newdate3"] <- data[1, "Date2"] - 10
class(data[1, "newdate3"]) # Date

Por cierto, no necesita as.Date cuando realiza operaciones matemáticas con objetos Date .

0
agregado