I have a problem with a "repeat" function in R - r

checknames <- function(){
gamers <- c("Rebeca","Luis","Paco")
games <- c("3","2","7")
scores <- c(100,110,50)
table <- data.frame(gamers,games,scores)
r=0
p=0
repeat{
print("Name Player 1: ")
name1=scan(,what="character",1)
for(i in 1:length(gamers)){
if(name1==gamers[i]){
r=readline(prompt = "This player is already in the file. Would you like to change the name? \n 1. Yes \n 2. No \n Select an option: ")
}
}
if(r==2){
break
}
if(r==0){
gamers=c(gamers,name1)
name1 <- data.frame(gamers=name1,games="1",scores="100")
table <- rbind(table,name1)
break
}
}
table
repeat{
print("Name Player 2: ")
name2=scan(,what="character",1)
for(i in 1:length(gamers)){
if(name2==gamers[i]){
print("This player is already in the file. Would you like to change the name?")
r=scan(,what="character",1)
}
}
if(p=="No"){
break
}
if(p==0){
gamers=c(gamers,name2)
name2 <- data.frame(gamers=name2,games="1",scores="100")
table <- rbind(table,name2)
break
}
}
table
}
table <-checknames()
I was doing a code that ask the user 2 names, and it should prove if the table has this name, and if it not, add it, and if it has the name, ask the player if he/she wants to change it.
The problem is that when the player say that he want to change the name, the repeat function do not ever break, I think that is because of I assign something wrong (I assign r==2/r==0) and that is why the repeat function still repeating.

I see a couple of issues with your code. We will focus on the 2nd repeat loop you've written for player 2.
First of all, we can simplify the the for(if( loop you use to check if the name has already been taken. by checking the list all at once instead of looping through the entire index.
if(any(name2==gamers)){
print("This player is already in the file. Would you like to change the name?")
r=scan(,what="character",1)
}
Now, moving on to some of your problems.you store the variable r in your scan but you are checking for the variable p. You should change the line in the above code block to read p=scan(,what="character",1).
Furthermore, you now have a situation where if your user2 put in a name already taken, then changed it to something else, your code will never let them out as you do not have never set p back to 0. This can be adressed by adding an else { p=<-0 } line.
All of the above changes are placed together here for you:
if(any(name2==gamers)){
print("This player is already in the file. Would you like to change the name?")
p=scan(,what="character",1)
} else {
p <- 0}

Related

Create a series of new folders in for loop in R

I have create a small script that passes a vector through a loop. In this loop I am using an if else statement to check if folder exists and if not to create the folder. However, I am getting error: Error in file.exists(i) : invalid 'file' argument. This has to due with file.exist(). I dont understand why this isnt ok. I check the man using help. Seems like this should be working.
folders<- c("RawData", "Output", "BCV", "DEplots", "DEtables", "PathwayOuts", "VolcanoPLots")
for(i in 1:length(folders)){
if (file.exists(i)){
cat(paste0(i, "already exists"))
} else {
cat(paste0(i, "does not exists"))
dir.create(i)
}
}
You are looping over an index (that is, 1:length(folders) is just the vector 1:7, not the values of the folders vector itself. The easiest solution is to loop over the vector itself:
for (i in folders) {
Or, if you still want to loop over the index:
for (i in 1:length(folders)) {
if (file.exists(folders[i])){
cat(paste0(folders[i], "already exists"))
}
else {
cat(paste0(folders[i], "does not exists"))
dir.create(folders[i])
}
}
A quick tip: if you are debugging a for-loop, the place to start is to add print(i) at the start of the loop. You would have immediately seen the problem: i was an integer, not the first value of the vector.

Saving data contained in a file

We are working in the Nought and Crosses game and we have the following problem:
We have created a function that suggests you to put 2 names. If you don't have any file saved, the function creates a new one. But, in the case that you already have one, we need the last archive to be edited and to add the new data without deleting the previous ones.
The following is the code we currently have
option1<-function() {
Name1=readline(prompt="Please enter the name of player 1: ")
Name2=readline(prompt="Please enter the name of player 2: ")
if(file.exists("C:\\Documents\\Playernames.txt")) {
Data=read.table("C:\\Users\\Documents\\Playernames.txt")
print(Data)
Newnames=c(Name1, Name2)
Newdata=data.frame(Newnames)
write.table(Newdata, "C:\\Documents\\Playernames.txt")
} else {
Names=c(Name1, Name2)
Data=data.frame(Names)
write.table(Data, "C:\\Users\\Documents\\Playernames.txt")
}
}

How to solve this error of conditional statements and Loops in R?

You can suggest me any sort of answers, not necessarily need using conditional statements and Loops.
I have the data set with several ids and and three alert or groups.
here is the image for the concept:
and here is the actual Data set for one ID: Click me
Concept is:
I have three alert: Relearn - Rebuild - Replace.
and after relearn: rebuild or replace can come but relearn cannot come
and after rebuild: replace can come but relearn cannot come
after replace: relearn and rebuild cannot come. if there is any replace only that can come
I have attached the image and Dataset for better clear understanding and Here is my try:
temp1 = NULL
temp2 = NULL
sql50 = NULL
for(i in 1:nrow(BrokenPins)) #First Loop
{
sql50 = sqldf(paste("select * from rule_data where key = '",BrokenPins[i,1],"'",sep = ""))
for(j in 1:nrow(sql50))
{ #Second Loop
while (head(sql50$Flag,1) == sql50$Flag[j] )
{
temp1 = sql50[j,]
temp2 = rbind(temp2,temp1)
print("Send")
if(j == 1 || sql50$Flag[j] == sql50$Flag[j-1])
{
j = j+1
}
else(sql50$Flag[j] > sql50$Flag[j-1])
{
break
}
}
}
}
First loop will go through each id and second loop will give me all the alert for that id.
so in the image i have added send and dont send. it wont be in actual table. that basically means send means copy it to new dataframe like i am doing above rbind in the code and dont send means dont copy it. This Above piece of code will run but only take the first and end it.
Finally, Based On above Data set Click me: that is for one ID (key), Flag (1 - Relearn, 2-Rebuild,3-replace). so based on this dataset. my output should have Row 1, 2 and 7 because First Relearn[Flag 1] came then Rebuild[Flag 2] then again relearn[Flag 1]cannot come, only rebuild [Flag 2] and replace[Flag 2] can.
can you help me solve this concept?
One thing I notice is that you use else and also provided a condition; you should only use else when you want every case that is not included in the condition of your if statement. Basically, instead of using else(sql50$Flag[j] > sql50$Flag[j-1]) you should be using else if(sql50$Flag[j] > sql50$Flag[j-1]).

R: Iterating Over the List

I am trying to implement following algorithm in R:
Iterate(Cell: top)
While (top != null)
Print top.Value
top = top.Next
End While
End Iterate
Basically, given a list, the algorithm should break as soon as it hits 'null' even when the list is not over.
myls<-list('africa','america south','asia','antarctica','australasia',NULL,'europe','america north')
I had to add a for loop for using is.null() function, but following code is disaster and I need your help to fix it.
Cell <- function(top) {
#This algorithm examines every cell in the linked list, so if the list contains N cells,
#it has run time O(N).
for (i in 1:length(top)){
while(is.null(top[[i]]) !=TRUE){
print(top)
top = next(top)
}
}
}
You may run this function using:
Cell(myls)
You were close but there is no need to use for(...) in this
construction.
Cell <- function(top){
i = 1
while(i <= length(top) && !is.null(top[[i]])){
print(top[[i]])
i = i + 1
}
}
As you see I've added one extra condition to the while loop: i <= length(top) this is to make sure you don't go beyond the length of the
list in case there no null items.
However you can use a for loop with this construction:
Cell <- function(top){
for(i in 1:length(top)){
if(is.null(top[[i]])) break
print(top[[i]])
}
}
Alternatively you can use this code without a for/while construction:
myls[1:(which(sapply(myls, is.null))[1]-1)]
Check this out: It runs one by one for all the values in myls and prints them but If it encounters NULL value it breaks.
for (val in myls) {
if (is.null(val)){
break
}
print(val)
}
Let me know in case of any query.

R code does not work when called from function

HI i just started learning R and finding this problem to be really interesting where I just run a code directly without wrapping in a function it works but when I place it inside a function it doesn't work, What can be possible reason?
fill_column<-function(colName){
count <- 0
for(i in fg_data$particulars) {
count <- count +1
if(grepl(colName, i) && fg_data$value[count] > 0.0){
fg_data[,colName][count] <- as.numeric(fg_data$value[count])
} else {
fg_data[,colName][count] <- 'NA'
}
}
}
fill_column('volume')
Where I am creating new column named volume it this string exists in particulars column.
I have added a comment where solution given by another question does not work for me, Please look at my comment below.
Finally I got it working but reading another answer on SO, here is the solution:
fill_column <- function(colName){
count <- 0
for(i in fg_data$particulars) {
count <- count +1
if(grepl(colName, i) && fg_data$value[count] > 0.0){
fg_data[,colName][count] <- as.numeric(fg_data$value[count])
} else {
fg_data[,colName][count] <- 'NA'
}
}
return(fg_data)
}
fg_data = fill_column('volume')
Now reason, Usually in any language when we modify global object inside any function it reflects on global object immediately but in R we have to return the modified object from function and then assign it again to global object to see our changes. or another way for doing this is to assign local object from within the function to global context using envir=.GlobalEnv.

Resources