I have this function code, in a file named utils.R where I create big and large functions to avoide overlaoding my original project.
While everything seems correct and my DataFrame (which has a column named Fecha cierre -closing date-) looks perfect, when I try to print Dates, all belonging to the previosuly mentioned column, the output is this: Ejemplo de fechas reales: 19737 19737 19737 19737 19737 19737 (integer numbers, if you run r as.Date(19737) = "2024-01-15, which is what I want. How can I fix this? I need to have dates, not integers
# utils.R
library(dplyr)
library(lubridate)
prepara_df_ordenado = function(df, fecha_inicio) {
fecha_inicio = as.Date(fecha_inicio)
req_cols = c("Fecha cierre", "Terna", "Terna_rep", "Tiempo imputado")
faltan = setdiff(req_cols, names(df))
if (length(faltan)) stop("Faltan columnas obligatorias: ", paste(faltan, collapse = ", "))
# --- Convertir "Fecha cierre" ---
if (inherits(df[["Fecha cierre"]], "Date")) {
cat("'Fecha cierre' ya es Date, se conserva sin cambios.\n")
} else {
# cat("\nNo es de tipo fecha. Se trata como numérico.\n")
# cat(paste0("La fecha de inicio es: ", fecha_inicio, " y es de clase ", class(fecha_inicio)))
df[["Fecha cierre"]] = as.Date(fecha_inicio) + (as.integer(df[["Fecha cierre"]]) - 1L)
# cat(paste0("\nLa columna 'Fecha cierre es de clase': ", class(df$`Fecha cierre`)))
}
stopifnot(inherits(df[["Fecha cierre"]], "Date"))
evolucion_input = NULL
if ("Evolución imputación" %in% names(df)) {
evolucion_input = df[["Evolución imputación"]]
df = dplyr::select(df, -`Evolución imputación`)
}
if (!is.numeric(df[["Tiempo imputado"]])) {
df[["Tiempo imputado"]] = suppressWarnings(as.numeric(df[["Tiempo imputado"]]))
}
df_ordenado = df %>%
arrange(Terna, `Fecha cierre`, Terna_rep) %>%
group_by(Terna) %>%
mutate(
`Media Acumulada` = cummean(`Tiempo imputado`),
`Media Previa` = dplyr::lag(`Media Acumulada`, default = 0)
) %>%
ungroup()
list(df_ordenado = df_ordenado, evolucion_input = evolucion_input)
}
iqr_check = function(prev_vals, new_val){
q1 = as.numeric(quantile(prev_vals, 0.25, na.rm = T))
q3 = as.numeric(quantile(prev_vals, 0.75, na.rm = T))
iqr = q3-q1
lim_inf = q1 - 1.5 * iqr
lim_sup = q3 + 1.5 * iqr
isTRUE(new_val >= lim_inf && new_val <= lim_sup)
}
crea_evolucion = function(terna_rep, media_previa, media_acumulada){
n = substr(terna_rep, nchar(terna_rep), nchar(terna_rep))
ifelse(n == "1" | media_previa == 0,
0,
((media_previa - media_acumulada)/media_previa)*100)
}
calcular_tiempo_objetivo = function(df, ventana = 5){
df$`Tiempo objetivo`= 0
df$Productividad = 0
ternas = unique(df$Terna)
for (terna in ternas){
sub_df = df[df$Terna == terna, , drop = F]
tiempos = numeric(0)
for (i in seq_len(nrow(sub_df))){
t_imp = sub_df$`Tiempo imputado`[i]
tiempos = c(tiempos, t_imp)
ultimos = tail(tiempos, ventana)
t_obj = mean(ultimos, na.rm = T)
if (length(ultimos) > 1){
t_obj = t_obj - (sd(ultimos, na.rm = T)/2)
}
df[df$Terna == terna, "Tiempo objetivo"][i] = t_obj
if (t_obj > 0){
prod = (t_obj - t_imp)/t_obj * 100
} else {
prod = 0
}
df[df$Terna == terna, "Productividad"][i] = prod
}
}
return(df)
}
#' Construye el dataset de imputaciones B
#'
#' Procesa el histórico **día a día** a partir de `df_ordenado`.
#'
#' @param df_ordenado data.frame/tibble con las columnas mínimas
#' `Fecha cierre`, `Terna`, `Tiempo imputado` y opcionalmente `Key`.
#' @param min_prev integer(1). Mínimo de observaciones previas a considerar
#' para validar/aceptar una imputación. Por defecto `3`.
#' @param incluir_rechazadas logical(1). Si `TRUE`, incluye explícitamente las
#' imputaciones rechazadas en el resultado. Por defecto `FALSE`.
#'
#' @return Un `data.frame` con columnas:
#' `Fecha cierre`, `Key`, `Terna`, `Tiempo imputado`, `Aceptada`,
#' `Rechazada`, `ultima_imputacion`, `repeticiones`.
#'
#' @details
#' El algoritmo recorre el histórico en orden por `Fecha cierre` y `Terna`,
#' calculando aceptación/rechazo según el criterio definido (p. ej. IQR/medias
#' previas) y añadiendo metadatos como `ultima_imputacion` y `repeticiones`.
#'
#' @examples
#' \dontrun{
#' res = construir_imputaciones_B(df_ordenado, min_prev = 3, incluir_rechazadas = FALSE)
#' head(res)
#' }
#'
#' @export
construir_imputaciones_B_dia_a_dia = function(df_ordenado, min_prev = 4, incluir_rechazadas = FALSE) {
df = arrange(df_ordenado, .data[["Fecha cierre"]])
# 🔒 Reforzar tipo inicial
df$`Fecha cierre` = as.Date(df$`Fecha cierre`)
cat("📅 Tipo inicial de 'Fecha cierre':", class(df$`Fecha cierre`), "\n")
base_cols = c("Key", "Terna", "Operario", "OP", "Fecha cierre","Puesto", "Mes",
"Tiempo imputado", "Media Previa","Media Acumulada",
"Fecha cierre", "Terna_rep", "Área")
historial = new.env(parent = emptyenv())
filas = list()
fila_idx = 1L
# --- Forzar que cada elemento de 'dias' sea Date ---
dias_raw <- unique(df$`Fecha cierre`)
dias_raw <- dias_raw[order(dias_raw)]
# 🔒 Crear vector garantizado de tipo Date
dias <- as.Date(sapply(dias_raw, function(x) as.Date(x, origin = "1970-01-01")), origin = "1970-01-01")
cat("📆 Ejemplo de días únicos (forzados):", head(dias), "\n")
for (dia in dias) {
# 🔍 Trazar tipo del día
if (fila_idx == 1L) cat("➡️ Tipo de 'dia' dentro del bucle:", class(dia), "\n")
df_dia = df[df[["Fecha cierre"]] == dia, , drop = FALSE]
# Verificar que sigue siendo Date tras subset
if (fila_idx == 1L) cat("📅 Tipo tras subset:", class(df_dia$`Fecha cierre`), "\n")
for (i in seq_len(nrow(df_dia))) {
r = df_dia[i, , drop = FALSE]
terna = as.character(r[["Terna"]])
t = as.numeric(r[["Tiempo imputado"]])
if (!exists(terna, envir = historial, inherits = FALSE)) {
assign(terna, numeric(0), envir = historial)
}
prev = get(terna, envir = historial)
suficientes = length(prev) >= min_prev
aceptar = if (!suficientes) TRUE else iqr_check(prev, t)
fila = as.data.frame(r[base_cols], stringsAsFactors = FALSE)
if ("Fecha cierre" %in% names(fila)) {
fila$`Fecha cierre` = as.Date(fila$`Fecha cierre`, origin = "1970-01-01")
}
if (aceptar) {
prev = c(prev, t)
assign(terna, prev, envir = historial)
filas[[fila_idx]] = fila
fila_idx = fila_idx + 1L
} else {
if (length(filas) > 0) {
filas = Filter(function(x) !identical(as.character(x$Terna[1]), terna), filas)
}
assign(terna, numeric(0), envir = historial)
}
}
}
imputaciones_B = do.call(rbind, filas)
# 🔍 Comprobamos tipo justo después del rbind
cat("🧩 Clase tras rbind:", class(imputaciones_B$`Fecha cierre`), "\n")
cat("🧩 Valores ejemplo:", head(imputaciones_B$`Fecha cierre`), "\n")
# ✅ Conversión correcta con origen explícito
imputaciones_B$`Fecha cierre` = as.Date(imputaciones_B$`Fecha cierre`, origin = "1970-01-01")
cat("✅ Clase final de 'Fecha cierre' en imputaciones_B:", class(imputaciones_B$`Fecha cierre`), "\n")
cat("🗓️ Ejemplo de fechas reales:", head(imputaciones_B$`Fecha cierre`), "\n")
imputaciones_B$Evolución_imputación_calc = crea_evolucion(
imputaciones_B$Terna_rep,
imputaciones_B$`Media Previa`,
imputaciones_B$`Media Acumulada`
)
imputaciones_B = calcular_tiempo_objetivo(imputaciones_B, ventana = 5)
list(imputaciones_B = imputaciones_B, historial = as.list(historial))
}