a is more than 1 and b is less than 1000. How do I input in a and b in R console instead of defining in the R script? I have read about the readline function but don't really understand it well.
a <- 3
b <- 4
y <- a*b
y
if((y %% 2) == 0) {
print(paste(y,"is Even"))
} else {
print(paste(y,"is Odd"))
}
You can use readline() function.
Example:
my.name <- readline(prompt="Enter name: ")
my.age <- readline(prompt="Enter age: ")
# convert character into integer
my.age <- as.integer(my.age)
print(paste("Hi,", my.name, "next year you will be", my.age+1, "years old."))
example
By just changing your first two lines using readline and wrapping the entire thing in {} You can combine your script into a clause.
{
a <- as.numeric(readline(prompt = "Enter a: ")) # Read in from console and change to number
b <- as.numeric(readline(prompt = "Enter b: ")) # Read in from console and change to number
y <- a*b
y
if((y %% 2) == 0) {
print(paste(y,"is Even"))
} else {
print(paste(y,"is Odd"))
}
}
This allows you to run the whole thing from top to bottom and take your inputs consecutively. You can also make this into a function.
Related
I have the following function in R. It is working fine, however, I think that must be a better way to run this function.
values <- c("a","b")
print <- function(values){
size <- length(values)
if (size == 1) {
final <- values[1]
}else if(size == 2){
final <- paste0(values[2], " and ", values[1])
}else if(size == 3){
final <- paste0(values[3], " and ",values[2], " and ", values[1])
}
return(final)
}
print(values)
The user can change the size of values, so if he choose values <- c("a","b", "c") the function is gonna run in the last condition. However, the last condition is in art equal to the second conditional plus something new. It is possible to make an if statement, or something in those lines that uses the previous condition . Something like:
values <- c("a","b", "c")
print <- function(values){
size <- length(values)
if (size == 1) {
final <- values[1]
}else if(size == 2){
final <- paste0(values[2], " and ", final )
}else if(size == 3){
final <- paste0(values[3], " and ",final )
}
return(final)
}
print(values)
Try this, which reverses the order of the input vector and pastes "and" between:
newfun <- function(x){
ifelse(length(x)>1, paste(rev(x), collapse = " and "), x)
}
Output:
newfun(letters[1])
# [1] "a"
newfun(letters[1:2])]
# [1] "b and a"
# and so on...
newfun(letters[1:5])
# [1] "e and d and c and b and a"
Testing this against your function to see if it is identical:
all.equal(print(letters[1:3]),
newfun(letters[1:3]))
# [1] TRUE
I would also strongly caution naming user-defined functions names that are already inherent in R (i.e. print() is already a function in R.
Another way of reversing the order of the vectors:
reverse_print <- function(values) paste(values[order(values, decreasing = TRUE)], collapse = " and ")
reverse_print(c("a", "b"))
#[1] "b and a"
reverse_print(c("a", "b", "c", "d"))
#[1] "d and c and b and a"
However, if your main objective is to create a function that recursively uses a condition and the previous conditions, one way of achieving it is to create a direct recursive function, in which the function calls itself (please see #G.Chan's comment for reference). Unfortunately, I failed to create such function for your case. Error: C stack usage 15927520 is too close to the limit was produced. This kind of error is relatively common in recursive functions, as discussed here.
Instead of crating a direct recursive function, I would suggest making the use of while along with incremented index as follows:
revprint <- function(values) {
size <- length(values)
if (size == 1) {
cat(values[1])
} else {
while (size > 1) {
final <- values[size]
appended <- paste0(final, " and ")
size <- size - 1
output <- cat(appended)
}
cat(output, values[1], sep = "")
}
}
revprint("a")
# a
revprint(c("a", "b", "c", "d"))
# d and c and b and a
If the length of the input (a character vector) is larger than 1, this function displays the final character of the input using paste0, and then incrementally reduces the length of the input. In each incremental step, the final character of the new (shorter) input is displayed, appended with the final character of the previous (longer) input.
Because this function uses cat, the result is displayed on the console, but it cannot be assigned directly to an object. To assign it to an object, you can use capture.output()
out <- capture.output(revprint(c("a", "b", "c", "d")))
out
#[1] "d and c and b and a"
I am trying to count the letters in the list by skipping 1 letter and grouping them in three until i find "t a c" in the data frame and then i want to group the rest of them in three by skipping 3 letters until i find "a t t"
example of what i am trying to say:
"agttacgtaattatgat"
it should do:
agt,gtt,tta,tac stop, gta,att stop ,atg,tga,gat
(data frame's name is agen)
my code for that:
y=c()
x=1
while(x<853){
x=x+1
rt<-paste(agen[x],agen[x+1],agen[x+2])
y=c(y,rt)
ff<-data.frame(y)
if(ff=="t a c"){break}
}
ay=c()
while(x<853){
x=x+3
art<-paste(agen[x],agen[x+1],agen[x+2])
ay=c(ay,art)
aff<-data.frame(ay)
if(aff=="a t t"){break}
}
the first one is working fine but the second one does not break.
there will be a lot of stops and starts in the code, so can you help me write a loop that can do the job?
I guess I know just roughly what you need, but here is a code example, that maybe does what you need. I used the example you specified and used a vector with your DNA bases as elements instead of a 'data frame'. I also changed some style things.
agen_string <- "agttacgtaattatgat"
# Is not a data frame, but a vector. I don't know, why you try to use a data frame.
agen <- strsplit(agen_string, split = "")[[1]]
y <- c()
x <- 0 # Start with 0. Otherwise, you wouldn't find 'tac' in the beginning
# Search for 'tac' triplett
while(x < length(agen)){
x <- x + 1
rt <- paste(agen[x], agen[x+1], agen[x+2], sep = "")
print(rt)
y <- c(y, rt)
#ff <- data.frame(y)
if(rt == "tac"){
print("stop")
break
}
}
ay <- c()
while(x < length(agen)) {
x <- x + 3
art <- paste(agen[x], agen[x+1], agen[x+2], sep = "")
print(art)
ay = c(ay,art)
#aff<-data.frame(ay)
if(art == "att"){
print("stop")
break
}
}
If you work more on DNA sequences, you may want to use a more specialized R-package, like Biostrings for example.
I want to create a program in R that takes integer user input and then adds it to the previous user input. ex. user input(say one day): 10, then (maybe the next day) user input: 15 --> output 25.Ideally this would accept nearly an infinite amount of input. here is what I have so far:
amount_spent <- function(){
i <-1
while(i<10){
n <- readline(prompt="How much did you spend?: ")
i<-i+1
}
print(c(as.integer(n)))
}
amount_spent()
Problems I have with this code are that it only saves the last input value, and it is difficult to control when User is allowed to input. Is there any way to save user input to a data that can be manipulated through readline()?
# 1.R
fname <- "s.data"
if (file.exists(fname)) {
load(fname)
}
if (!exists("s")) {
s <- 0
}
n <- 0
while (TRUE) {
cat ("Enter a number: ")
n <- scan("stdin", double(), n=1, quiet = TRUE)
if (length(n) != 1) {
print("exiting")
break
}
s <- s + as.numeric(n)
cat("Sum=", s, "\n")
save(list=c("s"), file=fname)
}
You should run the script like this: Rscript 1.R
To exit the loop press Ctrl-D in Unix, or Ctrl-Z in Windows.
An R-ish way to do it would be through closures. Here is an example for interactive use (i.e. within an R session).
balance_setup <- function() {
balance <- 0
change_balance <- function () {
n <- readline(prompt = "How much did you spend?: ")
n <- as.numeric(n)
if (!is.na(n))
balance <<- balance + n
balance
}
print_balance <- function() {
balance
}
list(change_balance = change_balance,
print_balance = print_balance)
}
funs <- balance_setup()
change_balance <- funs$change_balance
print_balance <- funs$print_balance
Calling balance_setup creates a variable balanceand two functions that can access it: one for changing the balance, one for printing it. In R, functions can only return a single value, so I bundle both functions together as a list.
change_balance()
## How much did you spend? 5
## [1] 5
change_balance()
## How much did you spend? 5
## [1] 10
print_balance()
## [1] 10
If you want many inputs, use a loop:
repeat{
change_balance()
}
Break the loop with Ctrl-C, Escape or whatever is used on your platform.
I am fairly new in R programming and want to grab keyboard entry to execute further programming codes. As the code as given here is executed, everything works all good but when the exit is entered the program is terminated and it didn't print y and z.
Could you please advise me how to use readline command in loop and execute other program lines after that loop?
n=1
a=1
y=c()
z=c()
x=""
while(x!="exit"){
x<-readline("Enter your name ")
library(stringr)
if(x!="exit" & str_detect(x,"N")){
y[n]=x
n=n+1
}else{
z[a]=x
a=a+1
}
}
print(y)
print(z)
This code works. I have copied it in a foo.R file as so :
# in "foo.R"
n = 1
a = 1
y = character()
z = character()
x = ""
library(stringr)
while (x!="exit") {
x <- readline("Enter your name\n")
if (x!="exit" & str_detect(x,"N")) {
y[n] = x
n = n+1
} else {
z[a] = x
a = a+1
}
}
print(y)
print(z)
And then, from my R console (with the proper working directory), I can run :
source("foo.R")
# Enter your name
# Bob
# Enter your name
# Nate
# Enter your name
# exit
# [1] "Nate"
# [1] "Bob" "exit"
and it seems to work just fine.
At the end of the following code I want to print n_species, but I first want to print "The number of species is" and then the value. How can I do this?
n_species <- 0
n_invisibility <- 0
for(i in Species) {
n_species <- n_species + 1
for(i in Invisibility){
if(i == "Y") {
n_invisibility <- n_invisibility + 1
}
else {
n_invisibility <- n_invisibility + 0
}
}
}
print(n_species)
print(n_invisibility)
Another option that allows to easily control formatting of numbers:
sprintf("The number of species is %i.", n_species)
print(paste("The number of species is",n_species))
Paste also takes the parameters sep, where the default is sep=" ", and collapse, which is basically separation for vectors, if you're trying to print one as a string (and more).