Execute a set of lines from another R file
If you're worried about the region of interest will be shifted once you add new lines upstream, then an alternative (or slightly modified) version of MrFlick's answer would be read as:
sourcePartial <- function(fn,startTag='#from here',endTag='#to here') {
lines <- scan(fn, what=character(), sep="\n", quiet=TRUE)
st<-grep(startTag,lines)
en<-grep(endTag,lines)
tc <- textConnection(lines[(st+1):(en-1)])
source(tc)
close(tc)
}
Now you need to put a small, unique hash tag just above and below of the region of interest. Such as "#from here" and "#to here"
Source only part of a file
Using the right tool for the job …
As discussed in the comments, the real solution is to use an IDE that allows sourcing specific parts of a file. There are many existing solutions:
For Vim, there’s Nvim-R.
For Emacs, there’s ESS.
And of course there’s the excellent stand-alone RStudio IDE.
As a special point of note, all of the above solutions work both locally and on a server (accessed via an SSH connection, say). R can even be run on an HPC cluster — it can still communicate with the IDEs if set up properly.
… or … not.
If, for whatever reason, none of the solutions above work, here’s a small module[gist] that can do the job. I generally don’t recommend using it, though.1
#' (Re-)source parts of a file
#'
#' \code{rs} loads, parses and executes parts of a file as if entered into the R
#' console directly (but without implicit echoing).
#'
#' @param filename character string of the filename to read from. If missing,
#' use the last-read filename.
#' @param from first line to parse.
#' @param to last line to parse.
#' @return the value of the last evaluated expression in the source file.
#'
#' @details If both \code{from} and \code{to} are missing, the default is to
#' read the whole file.
rs = local({
last_file = NULL
function (filename, from, to = if (missing(from)) -1 else from) {
if (missing(filename)) filename = last_file
stopifnot(! is.null(filename))
stopifnot(is.character(filename))
force(to)
if (missing(from)) from = 1
source_lines = scan(filename, what = character(), sep = '\n',
skip = from - 1, n = to - from + 1,
encoding = 'UTF-8', quiet = TRUE)
result = withVisible(eval.parent(parse(text = source_lines)))
last_file <<- filename # Only save filename once successfully sourced.
if (result$visible) result$value else invisible(result$value)
}
})
Usage example:
# Source the whole file:
rs('some_file.r')
# Re-soure everything (same file):
rs()
# Re-source just the fifth line:
rs(from = 5)
# Re-source lines 5–10
rs(from = 5, to = 10)
# Re-source everything up until line 7:
rs(to = 7)
1 Funny story: I recently found myself on a cluster with a messed-up configuration that made it impossible to install the required software, but desperately needing to debug an R workflow due to a looming deadline. I literally had no choice but to copy and paste lines of R code into the console manually. This is a situation in which the above might come in handy. And yes, that actually happened.
How can I run multiple lines of code in R
Click on header Tools
, then Global Options...
, then Code
, then Ctrl + Enter Executes
and choose Multi-line R statement
Define all functions in one .R file, call them from another .R file. How, if possible?
You can call source("abc.R")
followed by source("xyz.R")
(assuming that both these files are in your current working directory.
If abc.R is:
fooABC <- function(x) {
k <- x+1
return(k)
}
and xyz.R is:
fooXYZ <- function(x) {
k <- fooABC(x)+1
return(k)
}
then this will work:
> source("abc.R")
> source("xyz.R")
> fooXYZ(3)
[1] 5
>
Even if there are cyclical dependencies, this will work.
E.g. If abc.R is this:
fooABC <- function(x) {
k <- barXYZ(x)+1
return(k)
}
barABC <- function(x){
k <- x+30
return(k)
}
and xyz.R is this:
fooXYZ <- function(x) {
k <- fooABC(x)+1
return(k)
}
barXYZ <- function(x){
k <- barABC(x)+20
return(k)
}
then,
> source("abc.R")
> source("xyz.R")
> fooXYZ(3)
[1] 55
>
Execute R files through an R script
You can use the source
command and pass it the filename. try ?source
Run a R script for all files in a directory, and store the outputs in one common data frame
Unfortunately, the answer provided by Álvaro does not work as expected, since the output repeats the same number with different organisation names, making it really difficult to read. Actually, the number 20 is repeated 20 times, the number 11, 11 times, and so on. The information is there, but it is not accessible without further data treatment.
I was doing my own research in the meantime and I got to the following code. Finally I made it to work, but the data format was "matrix" "array"
, really confusing. Fortunately, I wrote the last lines to transpose the data, unlist the array and convert in a matrix, which is able to be converted in a data frame and manipulated as usual.
Maybe my explanation is not very useful, and since I am a newbie, I am sure the code is far from being elegant and optimised. Anyway, please review the code below:
library(purrr)
library(rjson)
library(dplyr)
library(tidyverse)
setwd("~/documentos/varios/proyectos/programacion/R/psa_twitter")
# Load data from files.
archivos <- list.files("./raw_data/json_files",
pattern = ".json",
full.names = TRUE)
psa_handles <- read_csv(file = "./raw_data/psa_handles.csv") %>%
select(Name, AKA, Twitter)
nr_archivos <- length(archivos)
calcula_cuentas <- function(a){
# Extract lists
json_data <- fromJSON(file = a)
org_aka <- json_data$id
org_meta <- json_data$metadata
org_name <- org_meta$company
twitter <- json_data$twitter
following <- twitter$following
# create an empty vector to populate
longitud = length(following)
names <- vector(length = longitud)
# loop to populate the empty vector with third element of the sub-list
for(i in 1:longitud){
names[i] <- following[[i]][3]
}
# create a data frame and change column name
names_list <- data.frame(sapply(names, c))
colnames(names_list) <- "usernames"
# Create a data frame with the correct formatting ready to comparison
org_handles <- data.frame(paste("@",
names_list$usernames,
sep="")
)
colnames(org_handles) <- "Twitter"
# merge tables
org_list <- inner_join(psa_handles, org_handles)
cuentas_db_org <- length(org_list$Twitter)
cuentas_total_org <- length(twitter$following)
results <- data.frame(Name = org_name,
AKA = org_aka,
Cuentas_db = cuentas_db_org,
Total = cuentas_total_org)
results
}
# apply function to list of files and unlist the result
psa <- sapply(archivos, calcula_cuentas)
psa1 <- t(as.data.frame(psa))
psa2 <- matrix(unlist(psa1), ncol = 4) %>%
as.data.frame()
colnames(psa2) <- c("Name", "AKA", "tw_int_outbound", "tw_ext_outbound")
# Save the results.
saveRDS(psa2, file = "rda/psa.RDS")
Related Topics
Produce an Inset in Each Facet of an R Ggplot While Preserving Colours of the Original Facet Content
Fill Area Between Two Lines, with High/Low and Dates
Insert Images Using Knitr::Include_Graphics in a for Loop
R: Adding Alpha Bags to a 2D or 3D Scatterplot
How to Select All Unique Combinations of Two Columns in an R Data Frame
How to Install the R Package Rgl on Ubuntu 9.10, Using R Version 2.12.1
Using 'Fread' to Import CSV File from an Archive into 'R' Without Extracting to Disk
How to Summarizing Data Statistics Using R
Colons Equals Operator in R? New Syntax
Returning a Vector of Class Posixct with Vapply
How Do Add a Column in a Data Frame in R
When Writing My Own R Package, I Can't Seem to Get Other Packages to Import Correctly
Add Missing Xts/Zoo Data with Linear Interpolation in R
How to Count the Observations Falling in Each Node of a Tree