1

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!

Hunter
  • 43
  • 1
  • 5
  • 1
    When I run your code, the data.frames in `waves` seem to be as your desired result, so I can't seem to replicate your problem. Have you maybe overlooked re-assigning the results in the `waves` list back to `w1` and `w2`? – teunbrand May 16 '19 at 19:01
  • Yes, that was the final step I was missing -- I didn't assign waves back to w1 and w2, so I solved it by doing: w1 = waves[[1]]. Thank you! – Hunter May 16 '19 at 19:37

3 Answers3

0

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
ljh2001
  • 391
  • 3
  • 17
0

(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.

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
0

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]]
Hunter
  • 43
  • 1
  • 5