How to use the `sink` function within another function in R?

大憨熊 提交于 2020-01-14 18:52:16

问题


I have a function fun that relies on an external function external (i.e., from some package). How can I collect all the warnings that come out of external in a character vector?

This is a minimal setup:

# External function from another package.
external <- function() {
    warning("warning from external...")
}


# Function meant to capture the warnings.
fun <- function() {
    # Create variable to store the warnings.
    warns <- vector("character")

    # Create connection for the sink.
    connection <- textConnection("warns", "wr", local = TRUE)

    # Start collecting.
    sink(connection, type = "message")

    # Call external function and produce a warning.
    external()

    # Reset the sink.
    sink(type = "message")

    # Close the connection.
    close(connection)

    return(warns)
}

The output, however looks like this:

x <- fun()
# Warning message:
# In external() : warning from external...

print(x)
# character(0)

I am not interested in suppressWarnings, but rather to log these warnings. When I use sink outside of a function it seems to work, just as indicated in this answer.


回答1:


You can use tryCatch for this:

fun <- function() {
  tryCatch(external(), warning = function(my_warn) my_warn$message)
}

x <-fun()

x
# [1] "warning from external..."



回答2:


You can try evaluate() function from evaluate package, if you want to store warnings in a character vector:

external <- function() {
  warning("warning from external...")
}

# Function meant to capture the warnings.
fun <- function() {
   #some operation
   x=1+2;
   warnings_ls = evaluate::evaluate(external())
   return(list(value=x,warn=warnings_ls))
}

x <- fun()

> a$warn[[1]]$src
[1] "warning from external..."

> a$value
[1] 3



回答3:


Supplementing the answers above, the warn option (see ?options) says:

sets the handling of warning messages. If warn is negative all warnings are ignored. If warn is zero (the default) warnings are stored until the top–level function returns. If 10 or fewer warnings were signalled they will be printed otherwise a message saying how many were signalled. An object called last.warning is created and can be printed through the function warnings. If warn is one, warnings are printed as they occur. If warn is two or larger all warnings are turned into errors.

In that sense, setting options(warn = 1) before the sink makes it possible for the warning messages can be captured. The warn can be reverted to default after resetting the sink (i.e., options(warn = 0)). Then, fun would look something like:

fun <- function() {
    # Print warnings as they occur.
    options(warn = 1)

    # Create variable to store the warnings.
    warns <- vector("character")

    # Create connection for the sink.
    connection <- textConnection("warns", "wr", local = TRUE)

    # Start collecting.
    sink(connection, type = "message")

    # Call external function and produce a warning.
    external()

    # Reset the sink.
    sink(type = "message")

    # Close the connection.
    close(connection)

    # Restore default warning behavior.
    options(warn = 0)

    return(warns)
}

With the following output:

fun()
# [1] "Warning in external() : warning from external..."


来源:https://stackoverflow.com/questions/57657901/how-to-use-the-sink-function-within-another-function-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!