R conditional loop, multiple lists - r

I need help stepping through a second loop in R when a test fails in my first loop. Here's the logic:
to start use config_list[1] from list
then download file path_list[1] from list
check if file passes test,
if so, download path_list[1 + 1] file from list and go back to step 3
if not, change config to next in list and go back to step 2 for failed file
Here's how far I've gotten:
path_list <- list("path1", "path2", "path3")
config_list <- list("a", "b", "c")
for (con in config_list) {
con[1] # set initial config
for (val in path_list) {
print(paste(val, "downloaded")) # download file
if (val == "path2"){ # check if file passes some test
con[1 + 1] # if above test fails change to con[1 + 1]
print(paste(val, "downloaded")) # download file again with new config ???
}
print(val)
}
}

Related

Read txt files and separate by the chr

I have a question on reading large txt files and separate it based on the character "TIME".
Each "TIME" represents the pressure of a spatial area at a particular point in time.
How should I write the readtext functions that recognize the "TIME" characters and split them ?
I would first create a folder so that I can save the new files in it. Also, I would put the original data file in this folder.
# setwd("....") # Set the working directory as the folder you just created.
I saved the data structure that you provided in "data.txt"
The following lines will split your data (which is in "data.txt" in my computer) into files that have consecutive names, such as "data1.txt", "data2.txt", and so on.
incon = file("data.txt", "r")
i = 0
while (TRUE) {
line = readLines(incon, n = 1)
if (length(line) == 0) {
break
}
if (regexpr("TIME:", line) > 0) {
if (exists("outcon")) close(outcon)
i = i + 1
outcon = file(paste("data", i, sep=""), "w")
writeLines(line, outcon)
} else {
writeLines(line, outcon)
}
}
close(outcon)

Recursion error in R (Fibonacci sequence)

So I am trying to learn R on my own and am just working through the online tutorial. I am trying to code a recursive function that prints the first n terms of the Fibonacci sequence and can't get the code to run without the error:
Error in if (nterms <= 0) { : missing value where TRUE/FALSE needed
My code does ask me for input before entering the if else statement either which I think is odd as well. Below is my code any help is appreciated.
#Define the fibonacci sequence
recurse_fibonacci <- function(n) {
# Define the initial two values of the sequence
if (n <= 1){
return(n)
} else {
# define the rest of the terms of the sequence using recursion
return(recurse_fibonacci(n-1) + recurse_fibonacci(n-2))
}
}
#Take input from the user
nterms = as.integer(readline(prompt="How many terms? "))
# check to see if the number of terms entered is valid
if(nterms <= 0) {
print("please enter a positive integer")
} else {
# This part actually calculates and displays the first n terms of the sequence
print("Fibonacci Sequence: ")
for(i in 0:(nterms - 1)){
print(recurse_fibonacci(i))
}
}
This is a problem of readline in non-interactive mode. readline does not wait for a keypress and immediately executes the next instruction. The solution below is the solution posted in this other SO post.
I post below a complete answer, with the Fibonnaci numbers function a bit modified.
recurse_fibonacci <- function(n) {
# Define the initial two values of the sequence
if (n <= 1){
n
} else{
# define the rest of the terms of the sequence using recursion
Recall(n - 1) + Recall(n - 2)
}
}
#Take input from the user
cat("How many terms?\n")
repeat{
nterms <- scan("stdin", what = character(), n = 1)
if(nchar(nterms) > 0) break
}
nterms <- as.integer(nterms)
# check to see if the number of terms entered is valid
if(nterms <= 0) {
print("please enter a positive integer")
} else {
# This part actually calculates and displays the first n terms of the sequence
print("Fibonacci Sequence: ")
for(i in 0:(nterms - 1)){
print(recurse_fibonacci(i))
}
}
This code is the contents of file fib.R. Running in a Ubuntu 20.04 terminal gives
rui#rui:~$ Rscript fib.R
How many terms?
8
Read 1 item
[1] "Fibonacci Sequence: "
[1] 0
[1] 1
[1] 1
[1] 2
[1] 3
[1] 5
[1] 8
[1] 13
rui#rui:~$
To make it work with Rscript replace
nterms = as.integer(readline(prompt="How many terms? "))
with
cat ("How many terms?")
nterms = as.integer (readLines ("stdin", n = 1))
Then you can run it as Rscript fib.R, assuming that the code is in the file fib.R in the current working directory.
Otherwise, execute it with source ("fib.R") within an R shell.
Rscript does not operate in interactive mode and does not expect any input from the terminal. Check what interactive () returns in both the cases. Rscript will return FALSE as it is non-interactive, but the same function when run within an R shell (with source ()) it will be true.
?readline mentions that it cannot be used in non-interactive mode. Whereas readLines explicitely connect to stdin.
The code works fine but you shouldn't enter it into the terminal as is. My suggestion: put the code into a script file (ending .R) and source it (get help about it with ?source but it's actually pretty straightforward).
In R-Studio you can simply hit the source button.

R: Let users use the console while inside a function, record their inputs and react

Is it possible to write a function in R which will hold its execution, giving the users control over the console (while in interactive mode of course), meanwhile recording their inputs, and continuing execution either:
after a certain input has been made
or after a certain output has been made
or a certain duration of time has passed
Example: ask the user a question (without using readline() for the answer)
question <- function() {
message("How much is 2 + 2?")
#let users take control of the console
#continue to next statement only if they input "2+2", or "4" or a minute has passed
#meanwhile record their last input similar to ".Last.Value", e.g.:
startTime <- Sys.time()
timeout <- FALSE
lastInput <- lastInput()
while (eval(parse(text = lastInput)) != 4 & !timeout) {
if (difftime(Sys.time(), startTime, units = "mins") > 1) {
timeout <- TRUE
}
lastInput <- lastInput()
}
if (timeout) {
stop("Sorry, timeout.")
} else {
message("Correct! Let's continue with this function:")
}
}
Where lastInput() is a function which "listens" to user input when it changes.
Obviously the above structure is tentative and won't give me what I want, some way to "listen" or "observe" and only react when the user inputs something to the console.
The final user experience should be:
> question()
How much is 2+2?
> #I'm the user, I can do whatever
> head(mtcars)
> plot(1:10)
> 3
> 2 + 2
[1] 4
Correct! Let's continue with this function:
Am I too optimistic or is there some R magic for this?
Thanks to #parth I have looked at swirl's source code and got acquainted with the addTaskCallback function. From the help file:
addTaskCallback registers an R function that is to be called each time a top-level task is completed.
And so we can make R check the users input ("top-level task") with a specific function, responding accordingly.
But since the swirl code is very "heavy", I think I need to supply a minimal example:
swirllike <- function(...){
removeTaskCallback("swirllike")
e <- new.env(globalenv())
e$prompt <- TRUE
e$startTime <- Sys.time()
cb <- function(expr, val, ok, vis, data=e){
e$expr <- expr
e$val <- val
e$ok <- ok
e$vis <- vis
# The result of f() will determine whether the callback
# remains active
return(f(e, ...))
}
addTaskCallback(cb, name = "swirllike")
message("How much is 2+2?")
}
OK, so the swirllike function evokes the 2+2 question, but it also declares a new environment e with some objects the user needs not know. It then adds the swirllike task callback to the task callback list (or rather vector). This "task callback" holds the cb function which calls the f function - the f function will run with every input.
If you run this, make sure you see the swirllike task callback with:
> getTaskCallbackNames()
[1] "swirllike"
Now the f function is similar to my sketch in the question:
f <- function(e, ...){
if (e$prompt) {
if (difftime(Sys.time(), e$startTime, units = "mins") > 1) {
timeout <- TRUE
stop("Sorry, timeout.")
}
if(!is.null(.Last.value) && .Last.value == 4) {
message("Correct! Let's continue with this function:")
e$prompt <- FALSE
while (!e$prompt) {
#continue asking questions or something, but for this example:
break
}
}
}
return(TRUE)
}
And don't forget to remove the swirllike task callback with:
removeTaskCallback("swirllike")

checking status of individual node of cluster created with parallel::makeCluster

Let's say I've created a cluster using: cl <- parallel::makeCluster(2) and I send a call to the first node using parallel:::sendCall(cl[[1]], f, arg).
I want to get the results of a specific node (in this case the first node). I can do that using parallel:::recvResult(cl[[1]]). However, this process blocks until a result is received. Is there any way to check the status of of a specific node? I.e. a status like "is processing" or "is finished".
I'd recommend using the standard socketSelect function. For example:
library(parallel)
cl <- makePSOCKcluster(3, outfile="")
# Send task to worker 1
x <- 2
parallel:::sendCall(cl[[1]], sqrt, list(x), tag=1)
# Wait up to 5 seconds for worker 1 to send the result back
ready <- socketSelect(list(cl[[1]]$con), timeout=5)
if (ready > 0) {
result <- parallel:::recvData(cl[[1]])
cat(sprintf("sqrt(%f) = %f\n", x, result$value))
} else {
cat("result not ready after five seconds\n")
}
See the source for the recvOneData.SOCKcluster function in the file snowSOCK.R for a more complete example.

how do you get the tail -50 of the remote file in R

I need to be able to login to a system and get to get the tail -50 of the file. I have teh following set of code but this gets the whole file. Since the file is so huge, I need to run the script every 10 minutes and get the last 50 lines of the file. This is what I have:
library(RCurl)
for(k in 1:2) {
day1<-day-k
day1<-format(day1, "%Y%m%d")
day_vector<-c(day_vector, day1)
}
servers<-c("ServerA", "ServerB","ServerC")
for (i in 1:length(servers)) {
for(j in 1:length(day_vector)) {
ser_day<-paste(servers[i], day_vector[j], sep=".")
url<-paste0(servers[i], ".example.net/opt/files/appl_log_")
url<-paste(url, ser_day, sep="")
url<-paste0("sftp://", url)
tryCatch({
x<-getURL(url, userpwd="account1:passwd1", connecttimeout=60)
writeLines(x, paste0(servers[i], ".txt"))
},error = function(e)
{
print("unable to get the file")
})
Is there any way to get the tail of the file?

Resources