Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For loop to conditionally flip sign of values in data frame

I am trying to create a for loop in R that will 1) identify a negative number is a column, 2) flip the sign to positive, 3) then flip the sign (in either direction) of select columns for the same row, and then create a factor identifying whether the signs were flipped for not.

Below is an example. I want all negative values in column "z" to become positive, and then for any row where this occurred (rows 4-8) I want the sign of values in column "y" flipped.

Example <- data.frame(x = 4:-3, y = -4:3, z = 2:-5)

   x  y  z
1  4 -4  2
2  3 -3  1
3  2 -2  0
4  1 -1 -1
5  0  0 -2
6 -1  1 -3
7 -2  2 -4
8 -3  3 -5

for (i in Example$z){
 if(sign(i) == -1){
 Example$z[i] <- (Example$z[i]*-1)
 Example$y[i] <- (Example$y[i]*-1)
 Example$Flip[i] <- "True"
 }
 else{
  Example$Flip[i] <- "False"
   }
 }

However, this for loop gives me the following:

   x  y  z Flip
1  4 -4  2 True
2  3 -3  1 True
3  2 -2  0 True
4  1 -1 -1 True
5  0  0 -2 True
6 -1 -1  3 True
7 -2 -2  4 True
8 -3 -3  5 True

What I wanted it to create is this:

   x  y  z Flip
1  4 -4  2 False
2  3 -3  1 False
3  2 -2  0 False
4  1  1  1 True
5  0  0  2 True
6 -1 -1  3 True
7 -2 -2  4 True
8 -3 -3  5 True

What am I doing wrong in the construction of this loop? Any help is greatly appreciated!

like image 795
Leesplez Avatar asked Oct 16 '22 05:10

Leesplez


1 Answers

In R, most of the times you can get away without using for loop

Example$Flip <- Example$z < 0 
Example$z[Example$Flip] <- -Example$z[Example$Flip]
Example$y[Example$Flip] <- -Example$y[Example$Flip]


Example
#   x  y z  Flip
#1  4 -4 2 FALSE
#2  3 -3 1 FALSE
#3  2 -2 0 FALSE
#4  1  1 1  TRUE
#5  0  0 2  TRUE
#6 -1 -1 3  TRUE
#7 -2 -2 4  TRUE
#8 -3 -3 5  TRUE

Using dplyr we could get this done in one chain operation

library(dplyr)

Example %>%
  mutate(Flip = z < 0, 
         z = ifelse(Flip, -z, z), 
         y = ifelse(Flip, -y, y))

As far as your for loop is concerned you are looping over values of z instead the looping should be on index of z or the rows of dataframe (1:nrow(Example)) instead. I made two changes in your code and the below should work.

Example$Flip = NA

for (i in seq_along(Example$z)){ #Change1
   if(sign(Example$z[i]) == -1){ #Change2
     Example$z[i] <- (Example$z[i]*-1)
     Example$y[i] <- (Example$y[i]*-1)
     Example$Flip[i] <- "True"
    }
   else{
     Example$Flip[i] <- "False"
   }
 }

Example
#   x  y z  Flip
#1  4 -4 2 False
#2  3 -3 1 False
#3  2 -2 0 False
#4  1  1 1  True
#5  0  0 2  True
#6 -1 -1 3  True
#7 -2 -2 4  True
#8 -3 -3 5  True
like image 69
Ronak Shah Avatar answered Oct 27 '22 09:10

Ronak Shah