I have a dataframe with 3 variables and 250K records. As an example consider

``> df <- data.frame(V1=c(1,2,4), V2=c("a","a","b"), V3=c(2,3,1))V1 V2 V31 a 22 a 34 b 1``

and want to swap values between V1 and V3 based on the value of V2 as follows:

if `V2 == 'b'` then `V1 <- V3` and `V3 <- V1`

resulting in

``V1 V2 V31 a 22 a 31 b 4``

I tried a do loop but it takes forever. If I use Perl, it takes seconds. I believe this task can be done efficiently in R as well. Any suggestions are appreciated.

Try this

``````> df <- data.frame(V1=c(1,2,4), V2=c("a","a","b"), V3=c(2,3,1))
> df[df\$V2 == "b", c("V1", "V3")] <- df[df\$V2 == "b", c("V3", "V1")]
> df
V1 V2 V3
1  1  a  2
2  2  a  3
3  1  b  4
``````

You can use `transform` to do this.

``````df <- transform(df, V3 = ifelse(V2 == 'b', V1, V3), V1 = ifelse(V2 == 'b', V3, V1))
``````

Editted I got tripped up with column names, sorry. This works.

If you don't mind the rows ending up in different orders, this is kind of a 'cute' way to do this:

``````dat <- read.table(textConnection("V1 V2 V3
1  a  2
2  a  3
4  b  1"),sep = "",header = TRUE)

tmp <- dat[dat\$V2 == 'b',3:1]
colnames(tmp) <- colnames(dat)
rbind(dat[dat\$V2 != 'b',],tmp)
``````

Basically, that's just grabbing the rows where `V2 == 'b'`, reverses the columns and slaps it back together with everything else. This can be extended if you have more columns that don't need switching; you'd just use an integer index with those values transposed, rather than just `3:1`.

Top