5

I want to swap two columns in a data.frame. I know I could do something like:

dd <- dd[c(1:4, 6:5, 7:10)]

But I find it inelegant, potentially slow (?) and not program-friendly (you need to know length(dd), and even have some cases if the swapped columns are close or not to that value...) Is there an easy way to do it without reassigning the whole data frame?

dd[2:3] <- dd[3:2]

Turns out to be very "lossy" because the [ <- only concerns the values, and not the attributes. So for instance:

(dd <- data.frame( A = 1:4, Does = 'really', SO = 'rock' ) )
dd[3:2] 
dd[2:3] <- dd[2:1]
print(dd)

The column names are obviously not flipped...

Any idea? I could also add a small custom function to my very long list, but grrr... should be a way. ;-)

Antoine Lizée
  • 3,743
  • 1
  • 26
  • 36
  • 2
    The `data.table` pacakge allows you to do reordering of columns w/out re-assignment, but the syntax probably doesn't get much cleaner than what you are doing- http://stackoverflow.com/questions/12232041/how-to-reorder-data-table-columns-without-copying – thelatemail Aug 09 '13 at 00:55
  • But it should be noted that `setcolorder` changes col order by reference. No copies are being made. So, it's *fast*. – Arun Aug 09 '13 at 00:58
  • 1
    It takes about 7 ms to reverse the columns in a 10 x 1e6 data frame. So unless you're doing this _all the time_, it's unlikely to be the bottleneck in your code, and you should worry about expressiveness, not speed. – hadley Aug 09 '13 at 02:15
  • @thelatemail Very good reference to "data.table", an incredibly awesome package. I almost mentioned it in my question, but wanted to keep it focused. So your comment is perfect, thanks ;-) – Antoine Lizée Aug 09 '13 at 19:30

2 Answers2

3

It's not a single function, but relatively simple:

dd[replace(seq(dd), 2:3, 3:2)]

  A   SO   Does
1 1 rock really
2 2 rock really
3 3 rock really
4 4 rock really
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
2

This:

dd[,2:3] <- dd[,3:2]

works, but you have to update the names as well:

names(dd)[2:3] <- names(dd)[3:2]
Ferdinand.kraft
  • 12,579
  • 10
  • 47
  • 69
  • Thanks, but I mentioned it in my question, it's not really what I am looking for. (I would like to avoid calling the names afterwards) – Antoine Lizée Aug 09 '13 at 19:28