Hunter
Hunter

Reputation: 43

Add columns to data frames with for loop

Variations of this question have been answered, but I am struggling to apply them to my dataset as someone relatively inexperienced with R/programming. I have several data frames and I am trying to use a for loop to create a new variable added to each of the data frames.

Each data frame has the exact same column names, but the data frames represent different time points (e.g., w1 is wave 1, w2 is wave 2, etc.).

I completed a for-loop to 1) reverse score several items, then 2) compute a new variable which is just a sum of several variables.

w1
cesd1   cesd2
0       0
1       1
2       1 


w2
cesd1   cesd2
3       0
1       2
2       1 

waves = list(w1, w2)

for(i in 1:length(waves)) {
waves[[i]]$cesd2R <- abs(waves[[i]]$cesd2 - 3)

waves[[i]]$cesdTot <- with(waves[[i]], cesd1+ cesd2R, na.rm = T)
}

I would like to get an output that includes all of the previous columns in each data frame PLUS the new columns I compute in the loop ("cesd2R" and "cesdTot") in each of the data frames.

w1
cesd1   cesd2  cesd2R cesdTot
0       0       3     3 
1       1       2     3



w2
cesd1   cesd2 cesd2R cesdTot
3       0     3      6
1       2     1      2 

When I run the loop, I get no errors but nothing seems to happen. What am I missing? Thank you very much!

Upvotes: 1

Views: 76

Answers (3)

Hunter
Hunter

Reputation: 43

I got some help from a colleague and solved my problem, which was simply missing the step of assigning "waves" back to each original data frame.

So the original code works:

w1
cesd1   cesd2
0       0
1       1
2       1 


w2
cesd1   cesd2
3       0
1       2
2       1 

waves = list(w1, w2)

for(i in 1:length(waves)) {
waves[[i]]$cesd2R <- abs(waves[[i]]$cesd2 - 3)

waves[[i]]$cesdTot <- with(waves[[i]], cesd1+ cesd2R, na.rm = T)
}

and I added:

w1 = waves[[1]]
w2 = waves[[2]]

Upvotes: 0

Gregor Thomas
Gregor Thomas

Reputation: 145965

(a) be careful of names, your code uses cesdR2 in one place, but your text and sample data use cesd2R.

(b) You're giving na.rm = TRUE as an argument to with(), which won't work as intended. + doesn't have space for an na.rm argument either, so this is one way to do it:

for(i in 1:length(waves)) {
  waves[[i]]$cesd2R <- abs(waves[[i]]$cesd2 - 3)
  waves[[i]]$cesdTot <- rowSums(waves[[i]][, c("cesd1", "cesd2R")], na.rm = TRUE)
}

because rowSums does accept an na.rm argument.

Upvotes: 0

ljh2001
ljh2001

Reputation: 463

Looks like you mistyped while creating your second object in the loop. Instead of cesd2R you typed cesdR2. Does that fix it?

> for(i in 1:length(waves)) {
+   waves[[i]]$cesd2R <- abs(waves[[i]]$cesd2 - 3)
+   waves[[i]]$cesdTot <- with(waves[[i]], cesd1+ cesd2R, na.rm = T)
+ }
> waves
[[1]]
  cesd1 cesd2 cesd2R cesdTot
1     0     0      3       3
2     1     1      2       3
3     2     1      2       4

[[2]]
  cesd1 cesd2 cesd2R cesdTot
1     3     0      3       6
2     1     2      1       2
3     2     1      2       4

Upvotes: 0

Related Questions