Estoy luchando con la manipulación de datos. Una de las columnas en mi hoja de datos contiene la fecha de nacimiento, pero para una ubicación los valores están desviados en 100 años.

Hice un pequeño marco de datos de ejemplo para explicar mi problema: las fechas para París / Berlín son correctas, quiero cambiar la fecha solo para aquellas filas con Londres como ubicación (para este ejemplo de 2028-3-25 a 1928-3- 25).

library(lubridate)
date <- as.Date(c('1950-11-1','2028-3-25','1940-3-14'))
location <- c("Paris", "London", "Berlin")
df <- data.frame(date, location)
df$date_new <- ifelse(df$location %in% c("London"), df$date - years(100), df$date)

Como puede ver, instalé el paquete lubridate e intenté usar una declaración if else, pero eso solo me da algunos números negativos en la nueva columna.

La solución probablemente sea muy simple, pero no puedo resolverlo y me está volviendo loco.

¡Gracias!

4
Hendrik 15 dic. 2016 a las 20:20

2 respuestas

La mejor respuesta

Prueba esto como alternativa

df$date_new <- df$date
df$date_new[df$location=="London"] <- df$date_new[df$location=="London"] - years(100)

O en lugar de df$date_new <- ifelse(df$location %in% c("London"), df$date - years(100), df$date)

Tratar

df$date_new <- ifelse(df$location %in% c("London"), as.character(df$date - years(100)), as.character(df$date))
4
dimitris_ps 15 dic. 2016 a las 17:27

ifelse está tomando los atributos de clase de la prueba:

El modo del resultado puede depender del valor de la prueba (ver los ejemplos), y el atributo de clase (ver oldClass) del resultado se toma de la prueba y puede ser inapropiado para los valores seleccionados entre sí y no.

A veces es mejor utilizar una construcción como

(tmp <- yes; tmp[!test] <- no[!test]; tmp), posiblemente extendido a manejar los valores perdidos en la prueba.

Por tanto, parece que es mejor no utilizar ifelse. Aquí hay una solución:

> df$date_new = df$date
> df[location == "London",]$date_new = df[location == "London",]$date_new - years(100)
> df
        date location   date_new
1 1950-11-01    Paris 1950-11-01
2 2028-03-25   London 1928-03-25
3 1940-03-14   Berlin 1940-03-14

Sin embargo, si desea utilizar ifelse, puede convertir el objeto en una fecha si especifica el origen estándar (un objeto en R)

> library(lubridate)
> date <- as.Date(c('1950-11-1','2028-3-25','1940-3-14'))
> location <- c("Paris", "London", "Berlin")
> df <- data.frame(date, location)
> df$date_new <- as.Date(ifelse(df$location == "London", as.Date(df$date - years(100)), df$date), origin = origin)
> df
        date location   date_new
1 1950-11-01    Paris 1950-11-01
2 2028-03-25   London 1928-03-25
3 1940-03-14   Berlin 1940-03-14
3
Señor O 15 dic. 2016 a las 17:30