2

R beginner here, who really misses Python's

import pandas as pd
import my_file_which_is_just_a_file_not_a_package as mf
out = mf.my_cool_function()

I have found a way to implement something similar to the former (assigning an alias to a package), but how to do the latter, i.e. how to assign an alias to an .R file (not a package) you are importing? E.g. you have put some functions you use frequently into a separate .R file, or you are dividing your program into multiple .R files to keep things tidy.

NB: this is NOT a duplicate of questions asking how to assign an alias to a package - I am talking about single R files, not packages.

I understand that the namespace library provides a functionality similar to import as for installed packages:

library(namespace)
registerNamespace('ggp', loadNamespace('ggplot2'))
data(iris)
ggp::ggplot(iris, ggp::aes(x = Petal.Length, y = Sepal.Length)) + ggp::geom_point()

I also understand that you can use import to import only certain functions from another .R file, e.g. from another script (not a package):

import::here(fun_a, fun_b, .from = "other_resources.R")
a <- fun_a(…)

Finally, you can use source to load another script.

But none of this addresses my point about importing with an alias.

Edit

Since I was asked, I am trying to learn some R because:

  • I am curious; last time I tried R was before the tidyverse "revolution"; I hated it at the time, found it obscure, arcane, and with extremely poor documentation. Everyone's saying how wonderful tidyverse is, so I'm curious to give R another try
  • I am unlikely to migrate all my workflow from Python to R, but there might be certain things that I might want to do in R. An example is reading large Excel files and exporting to SQL; both of these tasks are much faster in R. I can now import large xlsx files into SQL in a fraction of the time, then get Python to read from SQL and leave the rest of my workflow unchanged. I posted about it here, where I also explained why CSV is not the best option for me (please do not reply saying 'use CSV').
halfer
  • 19,824
  • 17
  • 99
  • 186
Pythonista anonymous
  • 8,140
  • 20
  • 70
  • 112
  • Why would you need to do this? Simply import the package (it won't slow down your system at all), and use whatever functions needed. There's no need to only import one part of `ggplot2`. You install, call it, and then use whatever functions you need. No need for an alias, for packages or files – papelr Apr 04 '19 at 17:44
  • I beg to differ. Without aliases, how can I be sure that there are no name conflicts? What if the same function is implemented, differently, in multiple packages? Even if there are no conflicts, calling al.fun() is a useful reminder of where fun() comes from. May I ask how familiar you are with other languages? I have found that this concept is alien to R and Matlab users (whose namespace implementation is atrocious), while seems very common sense to users of other languages. – Pythonista anonymous Apr 04 '19 at 17:50
  • Btw, my question was about R scripts, not packages. In Python, a function to calculate something may be available in multiple packages, and a few times I built my own version of that in a separate file (not package). Being able to call this_package.calc(), that_package.calc() , myfile.calc() and then compare results has been very useful to me. Eg I built a specific function to solve something numerically that is, for my cases, much faster than the commonly available packages. – Pythonista anonymous Apr 04 '19 at 17:53
  • 1
    does sourcing to an environment work https://stackoverflow.com/questions/39620669/source-script-to-separate-environment-in-r-not-the-global-environment – user20650 Apr 04 '19 at 18:23
  • @Gainz, I know that with `source` I can load a script, I did say that in my question. What I don't know is if/how I can load a script and assign an alias to it, so that I can have some_package::fun() and myscript::fun() without conflicts. @user20650 , thanks for the link, but (being a newbie) I didn't really understand if any of the answers there addresses my point. – Pythonista anonymous Apr 04 '19 at 18:33
  • @Pythonistaanonymous Yeah now I get your question, that's why I deleted my comment (when I saw that you already looked into source()). I would have also suggest you the namespace() package, but you already looked into it too. I am actually not sure you can use alias in R the same way you can in python. I know it works pretty good when using it for a package (like with the namespace package). Couldn't you make a package with all the functions you are often using? You could then use the alias like you want. You can make your own package in less than 10min with roxygen2 and devtools. – Gainz Apr 04 '19 at 18:50
  • If I can ask, why are you using R if you are already familiar with Python? – Gainz Apr 04 '19 at 18:53
  • 2
    @Pythonistaanonymous ; From the link, Id try something like : If your R function(s) are stored in `temp` : `txt = 'fun <- function(...) print("hello")' ; cat(txt, file=temp<-tempfile())` , you can load them into an environment `source(temp, local = my_alias<-new.env())`. Then call the function with `my_alias$fun()`. (but my 2c fwiw, just chuck the functions in a package) – user20650 Apr 04 '19 at 18:54
  • @user20650, that's brilliant - thanks! If you type it as an answer I'll accept it! – Pythonista anonymous Apr 04 '19 at 20:05
  • @Gainz - Cause R rocks. Python might be more general but R still kicks ass. – Dason Apr 04 '19 at 20:58
  • Let's not get into that, please. Both languages have amazing stuff and idiotic, non-sensical stuff. Namespaces in R is one example of a deeply flawed implementation – Pythonista anonymous Apr 04 '19 at 21:02
  • You're welcome @Pythonistaanonymous. (ps I've removed the wee bit at the end of your question that you edited in. I'm sympathetic but it creates a bit of unnecessary noise that detracts from a clear question. https://meta.stackoverflow.com/ provides a forum for such discussions) – user20650 Apr 04 '19 at 21:45

1 Answers1

3

Sounds like you want to define an environment and source a file into it. I find sys.source useful for this.

I have an example file called "my_test_script.R" which contains:

MYCONSTANT <- 3

testfun <- function(val){
  print(val)
}

testfun2 <- function(x){
  return(x + MYCONSTANT)
}

Now an example session reading that file into an environment so I can 'alias' the information inside of it as 'tstEnv':

> tstEnv <- new.env()
> sys.source(file = "my_test_script.R", envir = tstEnv, toplevel.env = tstEnv)
> tstEnv$testfun("it works")
[1] "it works"
> tstEnv$testfun2(0) 
[1] 3
> tstEnv$testfun2(1)
[1] 4
> tstEnv$MYCONSTANT # I can read my constants too
[1] 3
Dason
  • 60,663
  • 9
  • 131
  • 148
  • Thank you! How is this different from the solution proposed by @user20650? Are there some fundamental differences? – Pythonista anonymous Apr 04 '19 at 20:51
  • To be perfectly honest - I can't recall if the toplevel.env param is completely necessary. – Dason Apr 04 '19 at 20:52
  • @Pythonistaanonymous - I don't see another answer. I didn't read the comments to the question so maybe it's the same? – Dason Apr 04 '19 at 20:53
  • @Pythonistaanonymous Well the answer in the linked question is where I got the template for the code I have saved on my system I'm pretty sure. Looks like this question might actually be a candidate to be closed as a duplicate. – Dason Apr 04 '19 at 20:54
  • 1
    His syntax was: `source(temp, local = my_alias<-new.env())` . Please do not close it as a duplicate. That other question does not explicitly address how to import a script as an alias. it may sound totally obvious to experienced R users, but, for people coming from other languages, it is not! – Pythonista anonymous Apr 04 '19 at 20:56