В R тот же код нельзя вышить в пакетный файл виньетки. объект списка не может быть принужден к типу целого числа

Этот вопрос касается функции generate_msts() в пакете GRATIS.

Я добавляю кое-что новое (делаю, чтобы у функции были опции для преобразования ее вывода в прекрасный формат tribble или сохранение исходного формата «список») и готовлю обновление для CRAN.

Добавьте новый код, как показано ниже (детали кодов с примером показаны внизу вопроса)

Интересно, должен ли я получить индекс? Но кажется, что сгенерированные данные не имеют индекса?

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

В качестве руководства я обновляю соответствующий пример для этой функции в Vignette. Тогда вещи становятся проводными.

Если бы я не сохранил сгенерированный вывод временного ряда (например, x ‹- my_function()), виньетка не смогла бы получиться. (Однако я могу использовать эту функцию непосредственно в независимом обычном файле RMD)

Использование этого кода напрямую может отображать вывод внутри RStudio, но не может быть связано.

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

введите здесь описание изображения

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.

Но это работает нормально. Он может вязать виньетку и показывает заглавные буквы.

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

Однако очень неудобно каждый раз сохранять его перед использованием. Интересно, это из-за того, что в пакете есть какие-то настройки по умолчанию, или виньетка не меняется? Или есть какой-то дополнительный шаг, который мне нужно сделать после того, как я изменю функцию внутри пакета R? Или даже содержание if else, которое я добавляю, нуждается в улучшении?

Я попытался devtools::document("C:/Users/mreal/Documents/GitHub/package_name");devtools::install("C:/Users/mreal/Documents/GitHub/package_name") обновить функцию перестроения. Но это все равно не помогает виньетке.

Я также пробовал rm(list=ls()) в console. Это тоже не работает

Код, который я использовал в виньетке, показан ниже

Ссылка на гитхаб:

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)

(сгенерированный файл.R) Код R, используемый внутри пакета, показан ниже

** Ссылка на гитхаб**

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)
}

person Scarlett    schedule 09.09.2020    source источник
comment
Можешь попробовать else if( output_format == "tsibble") {res <- map(res, ~ {.x <- as_tsibble(.x$x); .x})}   -  person akrun    schedule 09.09.2020
comment
извините, есть опечатка. это .x$x <- as_tsibble(.x$x)   -  person akrun    schedule 09.09.2020
comment
Звучит странно. Hvae вы пробовали tibble::as_tsibble вместо as_tsibble? Идея заключалась в том, что он может странно загружать пакеты, поэтому указание «где» может устранить путаницу.   -  person Oliver    schedule 09.09.2020
comment
Пытался. Я не знаю, почему он продолжает говорить, что объект списка не может быть принужден к типу целого числа   -  person Scarlett    schedule 09.09.2020
comment
Не могли бы вы привести полный воспроизводимый пример? Без воспроизводимого примера действительно трудно догадаться, что пошло не так.   -  person Yihui Xie    schedule 13.09.2020
comment
Благодарю вас! Обновление вопроса. Код и пример показаны внизу вопроса со ссылкой на Github.   -  person Scarlett    schedule 13.09.2020
comment
@YihuiXie У меня проблемы возникают только при использовании rmarkdown/knitr. Можете ли вы взглянуть на мой ответ - думаю, вы знаете о вязании больше, чем кто-либо - может ли это быть причиной ошибки?   -  person Steffen Moritz    schedule 16.09.2020


Ответы (1)


Я пытался запустить это для вас - мое первое предположение было проблемой NAMESPACE. Но, похоже, это также связано с функцией generate_msts().

Я действительно не думаю, что это связано с первым сохранением его в переменной x.

Вот мои выводы:

НЕ РАБОТАЕТ:

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

x

НЕ РАБОТАЕТ:

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

НЕ РАБОТАЕТ:

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

print(x)

РАБОТАЕТ:

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

В случаях сбоя это всегда то же сообщение об ошибке, что и у вас:

Ошибка: обработка виньетки «QuickStart.Rmd» не удалась с диагностикой: объект «список» не может быть принудительно введен в тип «целое число»

Так как head(), str(), class() у меня всегда работали, а только print() не работали, я предполагаю, что это проблема с функцией печати. Таким образом, ваш обходной путь с сохранением его в переменной x работал нормально только потому, что вы не вызывали функцию печати.

Также важно, проблема возникала у меня только при использовании generate_msts() внутри Rmarkdown. Как я объясню позже, это кажется разумным, поскольку печать в Knitr отличается от печати на консоли.

Когда я изменяю ваш generate_msts() и пересобираю пакет:

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

Rmarkdown внезапно запускается без ошибок.

Я предполагаю, что это проблема с print() для ваших конкретных данных при взаимодействии с Knitr.

Печать в Knitr отличается от печати на консоли (возможно, поэтому она работает без rmarkdown)

Вот хорошая ссылка о пользовательских методах печати и вязании: https://cran.r-project.org/web/packages/knitr/vignettes/knit_print.html

До Knitr версии 1.6 печать объектов фрагментами кода R фактически эмулировала консоль R.

Я могу представить, что метод S3 для knit_print из пакета tsibble (который просто использует все методы печати из tibble?) может просто не работать должным образом для вашего конкретного набора данных (я имею в виду, что он работал для tsibble, который я создал с помощью tsibble() ). Но просто (дикое?) предположение... ошибка и поведение в целом действительно странные...

Изменить: вот также стек вызовов R Markdown для ошибки:

 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]], ...)

Должно быть похоже для вас, но если вы хотите получить это самостоятельно, вам нужно выполнить следующие команды в своем документе rmarkdown

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

Но, как вы можете видеть в стеке вызовов, ошибка вызвана base::print(x), которая вызывает метод S3 tibble:::print.tbl(x), затем этот метод внутренне вызывает tsibble:::format.tbl_ts , который вызывает tibble::trunc_mat, ... и где-то внутри вызывается ошибка.

Хорошо ... Я проследил за этим дальше по дороге и ... то, что в конце концов вызывает беспорядок внутри этих вызовов функций, - это параметры вязания, которые вы установили в начале.

Вы пишете в начале вашего 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)

Измените это на просто:

options(tibble.print_min = 5)

Должно работать тогда.

person Steffen Moritz    schedule 16.09.2020
comment
Спасибо за помощь! Да, и эта проблема (невозможно связать) возникает каждый раз, когда я пытаюсь дать другой функции опцию if else. (Generate_msts() — лишь один из них). - person Scarlett; 17.09.2020
comment
И эй, я не совсем понимаю, почему вы меняете код на tsibble(date = as.Date("2017-01-01") + 0:9,value = rnorm(10)) вместо моего исходного tsibble(res). Поскольку эти изменения могут устранить ошибку, но вопреки моему желанию, то есть дать данным ts (здесь вывод определяется как res) возможность преобразования в формат tsibble. Является ли этот измененный код просто примером, подтверждающим, что этот вопрос может относиться к print()? Я не использовал print() в этом ìf/else или vignette. То есть вы имеете в виду, помимо того, что я упомянул, другие коды R нужно изменить? - person Scarlett; 17.09.2020
comment
Да, просто чтобы показать, что это может работать. Вы использовали печать в виньетке. Если вы просто пишете my_function(seasonal.periods = c(7, 365), n = 800, nComp = 2,output_format="tsibble") без присвоения переменной, это автоматически вызывает print() (поскольку результат будет напечатан на консоли или, соответственно, при использовании rmarkdown в документе). - person Steffen Moritz; 17.09.2020
comment
Итак, просто чтобы объяснить это, когда вы просто вызываете myfunction() - тогда вывод печатается на консоли - если его вывод, например. tibble, то R не делает хороший вывод по умолчанию, где-то в пакете tibble есть метод S3 print.tbl, который определяет, как печатается tibble. Таким образом, вы в основном также вызываете print.tbl - когда вы вызываете функцию без присвоения переменной. - person Steffen Moritz; 17.09.2020
comment
Спасибо за объяснение, принцип довольно ясен! И относительно того, как решить эту проблему. Вы предлагаете мне изменить код на что-то вроде output <- if (output_format == "list") {res } else if (output_format == "tsibble") {x <- as_tsibble(res) print.tbl(x)}return(output)}? 1) Поскольку я использую tsibble() для данных временных рядов вместо tibble, есть ли функция, аналогичная print.tbl, которую я могу применить? 2) И я проверяю предоставленную вами ссылку Yihui, выглядит круто! Просто думаю, есть ли какая-то функция, которую мне нужно применить из его блога. Очень ценю! - person Scarlett; 17.09.2020
comment
Может быть, вы немного путаете вещи ... тиббл в основном тиббл. Как вы можете видеть, когда вы вызываете class() для объекта tsibble. Поэтому, когда вы печатаете таблицу, она автоматически вызывает print.tbl. - person Steffen Moritz; 17.09.2020
comment
добавил стек вызовов для ошибки для вас в ответ - person Steffen Moritz; 17.09.2020
comment
Печально, грустно, код, который я только что упомянул, все еще не может решить ошибку :( Проверяю ваш ответ сейчас - person Scarlett; 17.09.2020
comment
Любая идея, как структурировать tibble/tibble, чтобы соответствовать функции обработки/печати ввода? - person Scarlett; 17.09.2020
comment
Хорошо, я отладил это дальше - вам повезло, в конце концов это будет быстрое исправление. Что в глубине души на самом деле вызвало ошибку, так это первоначальные настройки опции Knitr. Смотрите конец моего ответа. - person Steffen Moritz; 18.09.2020
comment
Большое спасибо, вы очень добры и терпеливы. Но это еще больше создает еще одну проблему. Отзывы, которые я получаю от моего предыдущего выпуска пакета CRAN (по этой причине я изменил эту часть). Ошибка гласила: Пожалуйста, всегда устанавливайте пользовательские параметры (), рабочий каталог или par () после того, как вы изменили его в примерах, виньетках и демонстрациях. например: старый ‹- варианты (цифры = 3) ... варианты (старый) например. виньетка. Есть ли лучший способ избежать как вязания, так и этой ошибки крана? Большое спасибо - person Scarlett; 18.09.2020
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) напрямую? - person Scarlett; 18.09.2020
comment
Да, вы также можете полностью удалить всю часть об опциях (tibble.print_min = 5) - в любом случае по умолчанию 10. Так что большой разницы в rmarkdown нет. Он просто показывает первые 10 строк вместо первых 5 строк созданной вами таблицы. - person Steffen Moritz; 18.09.2020
comment
Еще один намек: ваша реализация этого комментария CRAN в любом случае была неправильной. Вы что-то там не так поняли. Как вы это сделали, делать сброс прямо в начале не имело вообще никакого смысла, так как вы пытались изменить настройки и через 1 строчку напрямую сбрасывали настройки. Параметры (tibble.print_min = original) должны были быть в конце фрагмента кода. Таким образом, в фрагменте кода вы сначала сохраняете старые настройки, затем меняете настройки - ЗАТЕМ вы делаете весь вывод, который вы хотите сделать с измененными настройками, - а затем вы сбрасываете старые настройки. - person Steffen Moritz; 18.09.2020
comment
Так приятно слышать объяснения и исправления! Имейте смысл! Тогда я удалю всю часть «варианта». - person Scarlett; 18.09.2020