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.
CodePudding user response:
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
CodePudding user response:
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
CodePudding user response:
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