Create vector using for loop with if else condition - r

How can I turn the 3 item output of the for loop below into a data frame. In attempting a solution, I've tried:
-Creating an object related to the for loop, but couldn't succeed
-Creating a matrix, to no effect
What code would turn the output into a vector or list?
> for(i in X$Planned)ifelse(is.na(i),print("ISNA"),print("NOTNA"))
[1] "NOTNA"
[1] "NOTNA"
[1] "ISNA"

sapply(x$Planned, function(elem) if (is.na(elem)) {"isNA"} else {"notNA"})
# this will do it!
# however, it will be slower than the vectorized form
ifelse(is.na(x$Planned), "isNA", "notNA")

Related

Using $ to find a column in loops in r not working

I have been trying to find an answer to this on stack but I can not.
It is a pretty simple question, I am basically trying to understand why in some cases the item in my loop will take on values but in other times it will not.
For example:
for (i in colnames(df)) {
print(unique(df$i)
}
Nothing appears, shouldn't it work? Should for the first iteration df$i take on df$names of column 1. However when I instead type df[i], it does. I am trying to understand how exactly i is taking on different names in the loop when it will work and when it will not.
Here is another example I am trying to understand
for (var in var_names) {
print(var)
var_vector <-sum(case_when(df$x == var ~ df$y)
table<- cbind(table,var_vector)
}
For this I thought that var_vector would be called something different each time like x_vector, y_vector, etc. However, instead it is just called var_vector for each iteration of the loop. Is there a way to specify in the loop make all the "var"'s in a loop take on that value. For example if you are familiar with stata `var'_vector would rename the vector different with each iteration.
I'm not totally sure that this is the best practice, but you could use assign. It really depends more on the context I think.
x <- LETTERS[1:3]
for(i in seq_along(x)){
assign(paste0(x[i], "_vector"), runif(10))
}
A_vector
#> [1] 0.4221484184 0.6695296315 0.3161487477 0.4168466690 0.1906193914
#> [6] 0.2252857985 0.0005740104 0.6336193492 0.7917131276 0.2764370542
B_vector
#> [1] 0.3575036 0.3554171 0.6053375 0.9268683 0.2017908 0.4303173 0.6608523
#> [8] 0.2539930 0.8057227 0.0895042
C_vector
#> [1] 0.1287253 0.4172858 0.2453591 0.2957820 0.2213195 0.2940916 0.6900414
#> [8] 0.5104015 0.8996254 0.7504864

Use lists/dataframes as items in for-loops in R

I am quite sure this is basic stuff, but I just can't find the answer by googling. So my problem:
I want to use a for-loop on a list of lists or data frames. But when you use list[i], you get all the values in the data frame instead of the data frame it self. Can anyone point out to me how to code this properly?
Example of the code:
a<-data.frame(seq(1:3),seq(3:1))
b<-data.frame(seq(1:3),seq(3:1))
l<-c(a,b)
Then l[1] returns:
> l[1]
$seq.1.3..
[1] 1 2 3
And I want it to just return: a
You can use the list function:
a<-data.frame(1:3,1:3)
b<-data.frame(3:1,3:1)
l<-list(a,b)
And access it's value with double brackets [[:
l[[1]]
l[[2]]
Ps: seq(1:3) and seq(3:1) outputs the same value, so I used 1:3 and 3:1. :)

Looping/printing over a list in R

Let's suppose I have a simple list
v <- list(vec1=c(1,2,3), vec2=c(3,4,5, 6))
I would like to loop over this list and perform some function on its element, so that as an output I get both: name of that particular element and output of the function. For example:
for (i in v)
{print(sd(i))
}
In this case, the output is:
[1] 1
[1] 1.290994
But I would like to see something like this:
$vec1
[1] 1
$vec2
[1] 1.290994
So that I can easily spot to which element each output refers, if I have many elements within my list. I know it has sth with the function names() to do, but I can't make it work.
Using the function names() and outputting a list:
result<-list()
for (i in 1:length(v))
{result[[i]]=sd(v[[i]])
}
names(result)<-names(v)
The downside of this method is that it will assign the wrong names if the resulting list is smaller or greater than the original list (for example, if you add a next statement on the loop or otherwise skip an element).
If possible, a much easier solution is to follow d.b's comment.

Process and update simultaneously bunches of data.frames/matrix in R

I have bunches of data.frames in R workspace. And I have exactly same processing to treat them. Since I am "lazy" to run the command for each data.frame one by one, I wish to treat them as a group and process them with a loop which saves time.
Let me say, simply, to apply as.data.frame to those matrix for example of my real serial data-processing.
# dummy data
set.seed(1026)
a<-matrix(rnorm(100),50,2)
b<-matrix(rnorm(100),50,2)
c<-matrix(rnorm(100),50,2)
# process data one-by-one which is not good
a<-as.data.frame(a)
b<-as.data.frame(b)
c<-as.data.frame(c)
I could do but it is time-consume. I turn to a lazy but quick way similar to*applydealing with rows or columns inside data.frame.
sapply(c(a,b,c),as.data.frame) or sapply(list(a,b,c),as.data.frame), or even:
> for (dt in c(a,b,c)){
+ dt<-as.data.frame(dt)
+ }
But, none of them make changes happened to the original three matrix.
> class(a)
[1] "matrix"
> class(b)
[1] "matrix"
> class(c)
[1] "matrix"
I wish to see all of them have been trans to data.frame.
Your problem is that you're using sapply, which simplifies results to vectors or matrices.
You want lapply instead:
lapply(list(a,b,c), as.data.frame)
Edit for the (generally frowned upon) practice of changing the objects systematically but keeping the object names the same:
for(i in c("a", "b", "c"))
assign(i, as.data.frame(get(i))
This should get you a list of 3 data.frames:
set.seed(1026)
lapply(1:3,function(x){as.data.frame(matrix(rnorm(100),50,2))})

Cannot create an empty vector and append new elements in R

I am just beginning to learn R and am having an issue that is leaving me fairly confused. My goal is to create an empty vector and append elements to it. Seems easy enough, but solutions that I have seen on stackoverflow don't seem to be working.
To wit,
> a <- numeric()
> append(a,1)
[1] 1
> a
numeric(0)
I can't quite figure out what I'm doing wrong. Anyone want to help a newbie?
append does something that is somewhat different from what you are thinking. See ?append.
In particular, note that append does not modify its argument. It returns the result.
You want the function c:
> a <- numeric()
> a <- c(a, 1)
> a
[1] 1
Your a vector is not being passed by reference, so when it is modified you have to store it back into a. You cannot access a and expect it to be updated.
You just need to assign the return value to your vector, just as Matt did:
> a <- numeric()
> a <- append(a, 1)
> a
[1] 1
Matt is right that c() is preferable (fewer keystrokes and more versatile) though your use of append() is fine.

Resources