Changing imported R function globally - r

I want to globally add a parameter to a function after import. So in future function calls the function should be always called with the set parameter.
In this case, I want to add the function parameter in_schema("abc") to the function tbl from dplyr.
Normally, I would use the source code and modify the function parameters, save and source it. But in this case, I am already failing to get a proper source code file.
getAnywhere("tbl.DBIConnection")
A single object matching 'tbl.DBIConnection' was found
It was found in the following places
registered S3 method for tbl from namespace dplyr
namespace:dplyr
with value
function (src, from, ...)
{
check_dbplyr()
tbl(dbplyr::src_dbi(src, auto_disconnect = FALSE), from = from,
...)
}
How could I modify the tbl-function (in a script file) so future calls always use a certain Scheme?
like so:
tbl(connection, table, in_schema("abc"))
without having to provide the in_schema parameter all the time.

Don't copy and modify the function, it's messy, do something like this instead :
tbl_abc <- function(src, from, ...){
tbl(src, in_schema("abc", from), ...)
}
btw tbl(connection, table, in_schema("abc")) is improper syntax, in_schema("abc") needs a second argument, and it's passed to the ..., which are not used by tbl.DBIConnection()

Related

Generic print function for S3 class

I have an S3 class, and I'm trying to work out how to set up a print function for it.
This part's good.
print.webglobe <- function(wg, ...){
"it worked!"
}
But, if I run devtools::check() on it, I get the following ominous message:
checking S3 generic/method consistency ... WARNING
print:
function(x, ...)
print.webglobe:
function(wg, ...)
I tried adding the additional code:
print <- function(wg, ...){
UseMethod("webglobe", wg)
}
But, with this present, print.webglobe() never seems to be accessed and my S3 class just prints as a list of some sort.
How can I set up this up correctly?
Change the wg to x. The formal arguments of a method have to match those of the generic because arguments from the generic call are passed, based upon name, to the method. That's why the print() isn't working the way you would expect because wg is being sent to the wg rather than the method's first argument.

Can I add a method to a function to receive as an argument another particular function?

I've created my immutable Tensor_field and a function nabla that acts on the tensor (that is nabla(a::Tensor_field) = do something.
I've added a method to function dot for the tensor: Base.dot(a::Tensor_field, b::Tensor_field) = do something....
Now I want to define a new behavior to function dot with nabla as an argument.
Something like Base.dot(nabla::function, a::Tensor_field) = do something different.
I know in Julia we are able to pass functions as arguments to other functions, but I couldn't find in the docs how to define a method for a "functional" argument.
If I type typeof(nabla) the output is My_Module_Name.#nabla, not a real DataType...
If you want it to work for any function, you can do
Base.dot(f::Function, a::Tensor_field) = do something different
If you only want it to work for the nabla function already defined, you can take advantage of what you have discovered, namely that each function has a unique type:
Base.dot(f::typeof(nabla), a::Tensor_field) = do something different
This will match only the function called nabla, which will now be called f inside the function dot.
Note that you can write ∇ as \nabla<TAB> and use it in your code instead of the word nabla. If your tensor field is called e.g. 𝐯 (written as \mbfv<TAB>), you can then write ∇⋅𝐯 in your Julia code! (The centered dot is written as \cdot<TAB>, and is an alias for the dot function.)

Call Arguments of Function inside Function / R language

I have a function:
func <- function (x)
{
arguments <- match.call()
return(arguments)
}
1) If I call my function with specifying argument in the call:
func("value")
I get:
func(x = "value")
2) If I call my function by passing a variable:
my_variable <-"value"
func(my_variable)
I get:
func(x = my_variable)
Why is the first and the second result different?
Can I somehow get in the second call "func(x = "value")"?
I'm thinking my problem is that the Environment inside a function simply doesn't contain values if they were passed by variables. The Environment contains only names of variables for further lookup. Is there a way to follow such reference and get value from inside a function?
In R, when you pass my_variable as formal argument x into a function, the value of my_variable will only be retrieved when the function tries to read x (if it does not use x, my_variable will not be read at all). The same applies when you pass more complicated arguments, such as func(x = compute_my_variable()) -- the call to compute_my_variable will take place when func tries to read x (this is referred to as lazy evaluation).
Given lazy evaluation, what you are trying to do is not well defined because of side effects - in which order would you like to evaluate the arguments? Which arguments would you like to evaluate at all? (note a function can just take an expression for its argument using substitute, but not evaluate it). As a side effect, compute_my_variable could modify something that would impact the result of another argument of func. This can happen even when you only passed variables and constants as arguments (function func could modify some of the variables that will be later read, or even reading a variable such as my_variable could trigger code that would modify some of the variables that will be read later, e.g. with active bindings or delayed assignment).
So, if all you want to do is to log how a function was called, you can use sys.call (or match.call but that indeed expands argument names, etc). If you wanted a more complete stacktrace, you can use e.g. traceback(1).
If for some reason you really wanted values of all arguments, say as if they were all read in the order of match.call, which is the order in which they are declared, you can do it using eval (returns them as list):
lapply(as.list(match.call())[-1], eval)
can't you simply
return paste('func(x =', x, ')')

Function doesn't do operations on dataset in R

I'm fairly new to R programming, so my question can appear naive.
I want to define all my functions of R in a single file, named functions.R, and call when I need them. I thought to use source().
That's my code:
main.R:
library(gstat)
library(lattice)
library(rgdal)
source("functions.R")
source("script_import.R")
script_import.R:
source("functions.R")
#Here I import the dataset named "dati"
dati<-read.csv2("/home/eugen/Documenti/file_da_importare.csv", header = TRUE, skip=4, dec = ",")
colnames(dati)<-c("provider", "ente", "nome_stazione", "long", "lat", "quota", "periodo_dati", "anni_dati", "tm_01", "tm_02", "tm_03", "tm_04", "tm_05", "tm_06", "tm_07", "tm_08", "tm_09", "tm_10", "tm_11", "tm_12", "remove", "tn_01", "tn_02", "tn_03", "tn_04", "tn_05", "tn_06", "tn_07", "tn_08", "tn_09", "tn_10", "tn_11", "tn_12", "remove1", "tx_01", "tx_02", "tx_03", "tx_04", "tx_05", "tx_06", "tx_07", "tx_08", "tx_09", "tx_10", "tx_11", "tx_12", "stato", "note", "nazione")
#That's the function call with which I have problems
clean_main_ds()
#If I use this commands instead of the function all works well
#dati$remove<-NULL
#dati$remove1<-NULL
functions.R:
clean_main_ds<-function(){
#I want to delete two columns
dati$remove<-NULL
dati$remove1<-NULL
cat("I'm exiting the function")
return(dati)
}
When compiling I don't receive any error, the function appears as declared in rstudio, is called by script_import.R, the cat() works well (so I imagine that there's no problem with the call), but the function doesn't delete the two columns. If I use the same commands ("dati$remove<-NULL") in script_import.R, instead of the function, all works well.
Where's the error? How can I do to let my function operate on a dataset defined in another file?
Thank you very much for the help,
Eugen
Ps: sorry for the errors in the language, I'm not english. I hope that the text is clear enough...
When you use the assignment operator <- within a function, it only does an assignment within the function's own environment. That is, the function creates a copy of the object dati, and then assigns NULL to elements remove and remove1 of dati within the function's environment.
Now when you use return, the function will return this modified copy of the original object dati. It will not modify the object dati in the global environment. If you do str(clean_main_ds()), you'll notice that that object is actually your data frame with the columns removed.
There's a couple of things you could do to get around this. First, you could specify your function using the assignment operator <<-, which will do assignment in the global environment instead of the function's own environment:
clean_main_ds<-function(){
#I want to delete two columns
dati$remove<<-NULL
dati$remove1<<-NULL
cat("I'm exiting the function")
return(dati)
}
(In fact, doing this, you don't even need the last line return(dati) in the function. By the time you get there your function has already done the modifications to your object in the global environment.)
Another option would be to just assign the value returned by your original function to the original data frame by
dati <- clean_main_ds().
Finally, you could just remove the columns from your data frame directly, without writing a function for it, by using indexes.
dati <- dati[ , -which(colnames(dati) %in% c("remove", "remove1"))]
(You could do this directly by just specifying the column numbers of the columns to remove instead of the which() segment. That part just looks up the indexes of the columns whose name is remove or remove1.)

Getting objects in a situation where their name matters

I have a list of functions that I'd like to make documentation for. My question is not about how to do this, but it provides a convenient example of something I'm curious about.
prompt takes a function and a character string as arguments, and writes a help file on that function to the file represented by the character string path. In looping over the files, using prompt(f,filename=...) doesn't work since f is of type character. I tried get(f), which pulls the function out just fine, but doesn't give prompt enough information to work with (see below). So how do I force a character element to return the whole object not just the function that it names?
files <- c("current.market","current.portfolio.bond","fund","genAccount","genHistory.market","history.market","maRketSim.version","summary.vasicek.discrete","vasicek.discrete")
for(f in files) {
prompt( get(f), filename=paste("c:/myproject/man/",f,".Rd",sep="") )
}
Error in prompt.default(get(f), filename = paste("F:/Documents/R-projects/maRketSim/man/", :
cannot determine a usable name
?prompt tells us that
Arguments:
object: an R object, typically a function for the default method.
Can be ‘missing’ when ‘name’ is specified.
So I think prompt() already does what you want:
> prompt(name = "print", filename = "print.Rd")
Created file named 'print.Rd'.
Edit the file and move it to the appropriate directory.
Which does produce the relevant Rd file:
> writeLines(readLines("~/print.Rd"))
\name{print}
\alias{print}
%- Also NEED an '\alias' for EACH other topic documented here.
\title{
%% ~~function to do ... ~~
}
\description{
%% ~~ A concise (1-5 lines) description of what the function does. ~~
}
\usage{
print(x, ...)
}
%- maybe also 'usage' for other objects documented here.
\arguments{
\item{x}{
%% ~~Describe \code{x} here~~
....
I should add, that get("foo") does return the actual function, it is just the way that prompt() is coded that it can't work with an anonymous function as returned by get().

Resources