-1

I am looking for an R function that allows swapping two elements in a data frame under a certain constraint.

For example:

If I have a dataframe (5rows, 5cols) and I want that all elements in column 2 that are greater than the corresponding elements in column 3 to be swapped. As a result, all the elements of column 2 greater than those of column 3 would move to column 3 and vice-versa.

Your help is much appreciated.

dww
  • 30,425
  • 5
  • 68
  • 111
Miguel_s
  • 79
  • 3
  • 1
    Welcome to Stack Overflow. Please [make this question reproducible](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) by including a small representative dataset in a plain text format - for example the output from `dput(yourdata)`, if that is not too large, and the desired example output. – neilfws Feb 10 '22 at 02:15

4 Answers4

0

Reproducible sample data:

set.seed(42)
dat <- as.data.frame(matrix(sample(10, size=25, replace=TRUE), nrow=5))
dat
#   V1 V2 V3 V4 V5
# 1  1  4  7 10  4
# 2  5  2  4  2  5
# 3  1 10  9  3  5
# 4  9  1  5  9  4
# 5 10  8  4  9  2

Working solution:

dat[c("V1", "V2")] <- lapply(list(pmin, pmax), function(fun) do.call(fun, dat[c("V1", "V2")]))
dat
#   V1 V2 V3 V4 V5
# 1  1  4  7 10  4
# 2  2  5  4  2  5
# 3  1 10  9  3  5
# 4  1  9  5  9  4
# 5  8 10  4  9  2
r2evans
  • 141,215
  • 6
  • 77
  • 149
0

You can use

set.seed(123)
x = as.data.frame(matrix(sample(1:25), nrow = 5))
#   V1 V2 V3 V4 V5
# 1 15 18  9 25  2
# 2 19 11 21 17 16
# 3 14  5 24  1  7
# 4  3 23 20 12  8
# 5 10  6 22 13  4

x[, 2:3] = t(apply(x[, 2:3], 1, sort))
#   V1 V2 V3 V4 V5
# 1 15  9 18 25  2
# 2 19 11 21 17 16
# 3 14  5 24  1  7
# 4  3 20 23 12  8
# 5 10  6 22 13  4
dww
  • 30,425
  • 5
  • 68
  • 111
0

You can use swap from seqinr :

x = as.data.frame(matrix(sample(1:25), nrow = 5))
x
#>   V1 V2 V3 V4 V5
#> 1  1  7 22  6 10
#> 2  9 17 16 13  2
#> 3 23 19 12 24 20
#> 4  3 14 15  5 25
#> 5 18  8 11 21  4
ind <- (x[2] > x[3])
seqinr::swap(x[ind, 2], x[ind, 3])
x
#>   V1 V2 V3 V4 V5
#> 1  1  7 22  6 10
#> 2  9 16 17 13  2
#> 3 23 12 19 24 20
#> 4  3 14 15  5 25
#> 5 18  8 11 21  4
slowowl
  • 664
  • 1
  • 13
0

In base R, this may done by changing the order of column index/names while specifying the row index

i1 <- with(dat, V1 > V2)
dat[i1, 1:2] <- dat[i1, 2:1]

data

dat <- structure(list(V1 = c(1L, 5L, 1L, 9L, 10L), V2 = c(4L, 2L, 10L, 
1L, 8L), V3 = c(7L, 4L, 9L, 5L, 4L), V4 = c(10L, 2L, 3L, 9L, 
9L), V5 = c(4L, 5L, 5L, 4L, 2L)), class = "data.frame", row.names = c(NA, 
-5L))
akrun
  • 874,273
  • 37
  • 540
  • 662