El visual del script R no se muestra en la web debido a un error de zona horaria

Un usuario Pregunto ✅

pcshingles

Tengo este problema solo en la aplicación web y no en el escritorio. Hice un visual R para tomar una serie de tiempo (datos diarios) y producir un gráfico de pronóstico y un visual de tabla. Cuando publico la aplicación en la web, aparece el siguiente error:

Error in as.POSIXlt.POSIXct(x, tz) : 
 
 (converted from warning) unable to identify current timezone 'C':
 
 please set environment variable 'TZ'
 

El código fuente está pegado en la parte inferior, aunque es un poco complicado … Creo que una de las llamadas a la función usa la función as.POSIXct para coaccionar un objeto de fecha de una cadena, y los datos proporcionados tienen la forma de » YYYY-MM-DD «, por lo que no estoy seguro de si es la falta de una marca de tiempo y una zona horaria en la cadena lo que le da un error, tal vez la llamada de la función para recibir la variable tz no devuelve nada significativo porque funciona bien en escritorio. Incluso he intentado configurar la variable tz y dar los parámetros tz adicionales en algunas de las llamadas a funciones. ¿Qué puedo hacer para resolver este extraño error?

Script de pronóstico de R (gráfico):

### R Script used for displaying a graph containing 6-month forecast
### aggregated by day.

# Libraries
library('ggplot2')
library('forecast')
library('tseries')
library('lubridate')

Sys.setenv(TZ='EST')

# Determine which column is the date column
firstCol = dataset[1,1]
secondCol = dataset[1,2]
isFirstDate <- grepl("[0-9]+-[0-9]+-[0-9]+", toString(firstCol))
isSecondDate <- grepl("[0-9]+-[0-9]+-[0-9]+", toString(secondCol))
dateColumn <- 1
valuesColumn <- 2
if(!isFirstDate){
  dateColumn <- 2
  valuesColumn <- 1
}
theDates <- data.frame(dataset[dateColumn])
names(theDates) <- c("date")
theValues <- data.frame(dataset[valuesColumn])
names(theValues) <- c("values")
dataset <- cbind(theDates, theValues)

# Get information on dataset, create date sequence
count <- nrow(dataset)
firstdate = dataset$date[1]
firstyear = as.double(substring(dataset$date[1], 1, 4))
lastdate = dataset$date[count]
lastyear = as.double(substring(dataset$date[count], 1, 4))
dataset$date <- lubridate::ymd(substring(dataset$date, 1,10))
dataset <- dplyr::arrange(dataset, date)

# Fill in the empty dates with zeros
# Get base values
i <- 2
x <- data.frame(dataset$values[1])
d <- data.frame(dataset$date[1])
names(x) <- c("values")
names(d) <- c("date")

# Loop through each value
while(i <= count){
  
  # Get current day, month values
  thisMonth <- substring(dataset$date[i],6,7)
  lastMonth <- substring(dataset$date[i-1],6,7)
  today <- substring(dataset$date[i],9,10)
  yesterday <- substring(dataset$date[i-1],9,10)

  # Add missing dates if applicable

  # Add as many days as differenced from last date entry
  if( ((as.numeric(yesterday) + 1) != as.numeric(today)) & (thisMonth == lastMonth)){
    
    # How many days do we need to fill in?
    daysToFill <- as.numeric(today)-as.numeric(yesterday)-1
    
    # Fill in the days
    while(daysToFill > 0){
      # Add to new dataset
      zeroValue <- data.frame(0)
      names(zeroValue) <- c("values")
      x <- rbind(x, zeroValue)
      dateValue <- sprintf("%s-%s-%s",substring(dataset$date[i],1,4), thisMonth, toString(as.numeric(substring(dataset$date[i],9,10)) - daysToFill))
      dateValue <- data.frame(as.character(as.Date(dateValue, tz = "EST")))
      names(dateValue) <- c("date") 
      d <- rbind(d, dateValue)
      
      # decrement the daysToFill counter
      daysToFill <- daysToFill - 1
    }
     
    # Case when the first days of month are skipped
  } else if(thisMonth != lastMonth){
    # Get amount of days to fill
    daysToFill <- as.numeric(today)-1
    
    # Add each day missing
    while (daysToFill > 0){
      # Append dataset
      zeroValue <- data.frame(0)
      names(zeroValue) <- c("values")
      x <- rbind(x, zeroValue)
      dateValue <- sprintf("%s-%s-%s",substring(dataset$date[i],1,4), thisMonth, as.character(daysToFill))
      dateValue <- data.frame(as.character(as.Date(dateValue, tz = "EST")))
      names(dateValue) <- c("date") 
      d <- rbind(d, dateValue)
      
      daysToFill <- daysToFill - 1
    }
  }

  # If no missing values exist, then continue and then add to original dataset
  i <- i + 1
}

# Append the dataset, then sort by date
dataset <- rbind(dataset, cbind(d,x))
dataset$date <- lubridate::ymd(dataset$date)
dataset <- dplyr::arrange(dataset, date)

#### Aggregate the Data (by day) ####
# Get base values
i <- 2
x <- data.frame(dataset$values[1])
d <- data.frame(dataset$date[1])
names(x) <- c("values")
names(d) <- c("date")
ptr <- 1
# update after transforming the dataset
count <- nrow(dataset)

# Loop through each value
while(i <= count){
  
  # Get current and previous months and years
  thisMonth <- substring(dataset$date[i],6,7)
  lastMonth <- substring(dataset$date[i-1],6,7)
  today <- substring(dataset$date[i],9,10)
  yesterday <- substring(dataset$date[i-1],9,10)
  
  # Compare month values, either greater or lower
  # Also compare year
  if( (today > yesterday) || (thisMonth != lastMonth)){
    
    # Increment pointer
    ptr <- ptr + 1
    
    # Add new row to Date representing new day
    de <- data.frame(dataset$date[i])
    names(de) <- c("date")
    d <- rbind(d, de)
    
    # Add new row to Values representing new aggregate
    dx <- data.frame(dataset$values[i])
    names(dx) <- c("values")
    x <- rbind(x, dx)
    
    # Otherwise, aggregate data
  } 
  else if( today == yesterday){
    
    x$values[ptr] <- x$values[ptr] + dataset$values[i]
    
  }
  
  # Finish loop, increment i
  i <- i + 1
}

dataset <- cbind(d,x)

# update after transforming the dataset
count <- nrow(dataset)
count
dataset
# Create time series object and forecasted ARIMA fit model
y = ts(dataset$values, start=c(firstyear, yday(firstdate)), frequency=365)
y <- tsclean(y)
fit = forecast(auto.arima(y), 183)

# Plot everything and format axis
plot(fit, xaxt="n")
a = seq(as.Date(firstdate, tz = "EST"), by="month", length=183 + count)
axis(1, at = decimal_date(a), labels = format(a, "%Y %b %d"), cex.axis=0.6, ylab = 'value')
abline(v = decimal_date(a), col="grey", lwd=0.5)

pcshingles

Me lo imaginé. Una de las importaciones de la biblioteca estaba rompiendo todo el código porque no podía obtener una buena variable de zona horaria del sistema. Todo lo que tenía que hacer era establecer la zona horaria antes de que se importara la biblioteca. Ojalá los errores fueran más fáciles de leer y más informativos en la web …

Anónimo

Esta solución no funcionó para mí, pero descubrí cómo evitar tropezar con la necesidad de lubridate de una zona horaria: primero, solo tome la columna de fecha y hora con como.POSIXct, luego use lubridate, cuando sea útil, para calcular esos valores.

library('lubridate')
dataset$Time <- as.POSIXct(dataset$Time,format="%Y-%m-%dT%H:%M:%OS")
dataset$Time <- dataset$Time + minutes(5)

Creo que MS debería documentar mejor la forma en que se construye el conjunto de datos. Supongo que es demasiado tarde para transferir siempre columnas de tiempo de datos con valores POSIXct en lugar de valores de texto.

pcshingles

Me lo imaginé. Una de las importaciones de la biblioteca estaba rompiendo todo el código porque no podía obtener una buena variable de zona horaria del sistema. Todo lo que tenía que hacer era establecer la zona horaria antes de que se importara la biblioteca. Ojalá los errores fueran más fáciles de leer y más informativos en la web …

En respuesta a pcshingles

Hola @pcshingles,

¡Es bueno saber que el problema se resolvió!

¿Podrías aceptar tu respuesta anterior como solución para cerrar este hilo? Smiley feliz

Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *