Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In R, the same code cannot be knit out in package Vignette file. "list" object cannot be coerced to type integer

This question is about generate_msts() function in package GRATIS.

I add some new stuff (make the function has options to transform its output into a lovely tsibble format or keep the original ‘list’ format) and prepare update to CRAN.

New code add as below (detail of the codes with example shown at the bottom of the question)

I wonder should I get tsibble a index? But the generated data seems like do not have a index?

  output <- if (output_format == "list") {
    res                                    #this is output name defined before
  } else if (output_format == "tsibble") {
    as_tsibble(res)
  }
  return(output)
}

And as a guidance, I update the corresponding example for this function in Vignette. Then things become wired.

If I did not save the generated time series output (e.g. x <- my_function()), the vignette cannot knit out. (However, I can use this function directly in an independent normal RMD file)

Use this code directly can show output inside RStudio, but cannot be knit out.

my_function(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble")

enter image description here

Error in Fun(X[[i]],...): 'list' object cannot be coerced to type 'integer' Calls: <Anonymous>... 
as.data.frame -> head  -> head.data.frame -> lappy -> FUN Execution halted.

But, this works fine. It can knit out the vignette and shows head of tsibble.

x <- my_function(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble")
head(x)

However, this is very inconvenience to save it each time before you can use it. I wonder if this is because there is any default setting I used in package or vignette does not change? Or there is some extra step I need to do after I change the function inside R package? Or even the if else content I add need to be improved?

I have tried devtools::document("C:/Users/mreal/Documents/GitHub/package_name");devtools::install("C:/Users/mreal/Documents/GitHub/package_name") to update the re-build function. But this still does not help vignette.

I also tried rm(list=ls()) in console. It does not work as well

Code I used in vignette is as below

Github link:

https://github.com/BocongZhao823/gratis/blob/master/vignettes/QuickStart.Rmd

---
title: "Introduction to gratis"
author: "Bocong Zhao"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to gratis}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

{r initial, echo = FALSE, cache = FALSE, results = 'hide'}
library(knitr)
opts_chunk$set(
  warning = FALSE, message = FALSE, echo = TRUE,
  fig.width = 7, fig.height = 6, fig.align = 'centre',
  comment = "#>"
)
original <- options("tibble.print_min")
options(tibble.print_min = 5)
# <---- Do stuff with changed option, e.g. print some tibbles ----> 
options(tibble.print_min = original)


{r, message=FALSE, include = FALSE}
library(forecast)
library(tsibble)

{r setup}
# load package
library(gratis)

## Generate mutiple seasonal time series

Time series can exhibit multiple seasonal pattern of different length, especially when series observed at a high frequency such as daily or hourly data.

We use function **generate_msts()** to generate mutiple seasonal time series.

**Definitions**

Here are the definitions of parameter settings in function generate_msts():

|parameter settings | Definition|
|:----|:-----|
|seasonal.periods | a vector of seasonal periods of the time series to be generated|
|nComp|number of mixing components when simulating time series using MAR models|
|n    |length of the generated time series|

**Example**

Suppose we want to use MAR model to generate a time series with **2** mixing components and the length **800** from random parameter spaces. Particularly, this time series has two seasonal periods **7** and **365**.

{r fig.height = 6, fig.width = 7}
# Generate mutiple seasonal time series with 'tsibble' output format
x <- generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble")
head(x)

**Plot time series**

{r fig.height = 6, fig.width = 7}
# Generate mutiple seasonal time series with 'list' output format
x <- generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="list")
autoplot(x)

(generated.R file) The R code used inside a package is as below

** Github link**

https://github.com/BocongZhao823/gratis/blob/master/R/generate_ts.R

#' Generate mutiple seasonal time series from random parameter spaces of the mixture autoregressive (MAR) models.
#'
#' Generate mutiple seasonal time series from random parameter spaces of the mixture autoregressive (MAR) models.
#' @param seasonal.periods a vector of seasonal periods of the time series to be generated.
#' @param n length of the generated time series.
#' @param nComp number of mixing components when simulating time series using MAR models.
#' @param output_format An optional argument which allows to choose output format between "list" and "tsibble"
#' @return a time series with multiple seasonal periods.
#' @export
#' @examples
#' x <- generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2, output_format= "list")
#' forecast::autoplot(x)
generate_msts <- function(seasonal.periods = c(7, 365), n = 800, nComp = NULL,output_format="list") {
  x.list <- map(seasonal.periods, function(p) {
    generate_ts(n.ts = 1, freq = p, n = n, nComp = nComp)$N1$x
  })
  names(x.list) <- paste0("Season", seasonal.periods)
  x.list[1:(length(x.list) - 1)] <- lapply(x.list[1:(length(x.list) - 1)], function(x) {
    x - trendcycle(stl(x, "per"))
  })
  weights <- msts_weights(length(seasonal.periods))
  res <- as_tibble(scale(x.list %>% bind_cols())[, ]) %>%
    mapply("*", ., weights) %>%
    as_tibble() %>%
    mutate(x = rowSums(.)) %>%
    select(x) %>%
    msts(seasonal.periods = seasonal.periods)
  # New content
  output <- if (output_format == "list") {
    res
  } else if (output_format == "tsibble") {
    as_tsibble(res)
  }
  return(output)
}

# ===========================================================================
# Simulated weights for the simulation of msts
# ===========================================================================
msts_weights <- function(n.periods) {
  gamma <- runif(n.periods, 0)
  weights <- gamma / sum(gamma)
  return(weights)
}
like image 483
Flora Avatar asked Sep 09 '20 04:09

Flora


People also ask

Why can't I knit R markdown?

No Knit HTML button This means that RStudio doesn't understand your document is supposed to be an RMarkdown document, often because your file extension is . txt . To fix this, go to the Files tab (lower right corner, same pane as Plots and Help) and select the checkbox next to your document's name.

How do you make a package vignette in R?

To create a package vignette in R Markdown, the easiest way is through the RStudio menu File -> New File -> R Markdown -> From Template (see Figure 16.4). Then you select “Package Vignette” from the rmarkdown package, and you will get a vignette template.

What is vignette in R package?

Function documentation is great if you know the name of the function you need, but it's useless otherwise. A vignette is like a book chapter or an academic paper: it can describe the problem that your package is designed to solve, and then show the reader how to solve it.

What does knit function do in R?

Rendering Output There are two ways to render an R Markdown document into its final output format. If you are using RStudio, then the “Knit” button (Ctrl+Shift+K) will render the document and display a preview of it.

What does (list) object cannot be coerced to type double mean in R?

One common error you may encounter in R is: Error: (list) object cannot be coerced to type 'double'. This error occurs when you attempt to convert a list of multiple elements to numeric without first using the unlist () function. This tutorial shares the exact steps you can use to troubleshoot this error.

What is list in R with example?

R - Lists. Lists are the R objects which contain elements of different types like − numbers, strings, vectors and another list inside it. A list can also contain a matrix or a function as its elements.

What does (list) object cannot be coerced to type'double'mean?

One common error you may encounter in R is: Error: (list) object cannot be coerced to type 'double' This error occurs when you attempt to convert a list of multiple elements to numeric without first using the unlist () function. This tutorial shares the exact steps you can use to troubleshoot this error.

How to convert a list to a numeric vector in R?

Example 2 explains how to adequately convert a list to a numeric vector in R. Have a look at the following R code: As you have seen, we used a combination of the unlist and as.numeric functions, i.e. first we are converting our list to a vector and then we convert this vector to numeric. Works smoothly!


1 Answers

I tried to run this for you - my first guess was a NAMESPACE problem. But it seems also related to the generate_msts() function.

I really don't think this has to do with first saving it to a variable x.

Here are my findings:

DOES NOT WORK:

x <- generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble")

x

DOES NOT WORK:

print(generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble"))

DOES NOT WORK:

x <- generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble")

print(x)

WORKS:

 head(generate_msts(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble"))

In the failure cases it is always the same error message as for you:

Error: processing vignette 'QuickStart.Rmd' failed with diagnostics: 'list' object cannot be coerced to type 'integer'

So since head(), str(), class() always worked for me and only print() did not work, I am assuming it is a problem with the print function. So your workaround with saving it into variable x only worked fine, because you did not call the print function.

Also important the problem only occurred for me when using generate_msts() inside Rmarkdown. As I explain later this seems reasonable, since printing in knitr is different from printing on the console.

When I alter your generate_msts() and rebuild the package:

output <- if (output_format == "list") {
    res
  } else if (output_format == "tsibble") {
    tsibble(date = as.Date("2017-01-01") + 0:9,value = rnorm(10))
  }

The Rmarkdown suddenly runs without an error.

My guess would be it is a problem with the print() for your specific data in interaction with knitr.

Printing in knitr seems to be different from printing on the console (might be why it works without rmarkdown)

Here is a nice link about custom print methods and knitr: https://cran.r-project.org/web/packages/knitr/vignettes/knit_print.html

Before knitr v1.6, printing objects in R code chunks basically emulates the R console.

I could imagine the S3 method for knit_print from the tsibble package (which just uses all the printing methods from tibble?) might just not work properly for your specific dataset (I mean it worked for the tsibble I created with tsibble() ). But just a (wild?) guess...the error and behavior overall is really strange ...

Edit: Here is also the R Markdown callstack for the error:

 1. ├─base::print(x)
  2. └─tibble:::print.tbl(x)
  3.   ├─cli::cat_line(format(x, ..., n = n, width = width, n_extra = n_extra))
  4.   │ └─base::paste0(..., collapse = "\n")
  5.   ├─base::format(x, ..., n = n, width = width, n_extra = n_extra)
  6.   └─tsibble:::format.tbl_ts(x, ..., n = n, width = width, n_extra = n_extra)
  7.     ├─base::format(trunc_mat(x, n = n, width = width, n_extra = n_extra))
  8.     └─tibble::trunc_mat(x, n = n, width = width, n_extra = n_extra)
  9.       ├─base::as.data.frame(head(x, n))
 10.       ├─utils::head(x, n)
 11.       └─utils:::head.data.frame(x, n)
 12.         └─base::lapply(...)
 13.           └─utils:::FUN(X[[i]], ...)

Should be similar for you, but if you want to get this on your own, you have to the following commands to your rmarkdown document

options(rlang_trace_top_env = rlang::current_env())
options(error = function() {
  sink()
  print(rlang::trace_back(bottom = sys.frame(-1)), simplify = "none")
})

But as you can see in the callstack, the error is caused by base::print(x), which calls the S3 method tibble:::print.tbl(x), this method then internally calls tsibble:::format.tbl_ts, which calls tibble::trunc_mat, ... and somewhere inside the error is caused.

Ok ... I followed this further down the road and ... what in the end messes inside these function calls, are the knitr options you set in the beginning.

You write at the beginning of your rmarkdown:

original <- options("tibble.print_min")
options(tibble.print_min = 5)

# <---- Do stuff with changed option, e.g. print some tibbles ----> 
options(tibble.print_min = original)

Change this to just:

options(tibble.print_min = 5)

Should work then.

like image 200
Steffen Moritz Avatar answered Oct 27 '22 03:10

Steffen Moritz