1
votes

Imagine there are 4 cards on the desk and there are several rows of them (e.g., 5 rows in the demo). The value of each card is already listed in the demo data frame. However, the exact position of the card is indexed by the pos columns, see the demo data I generated below.

To achieve this, I swap the cards with the [] function across the rows to switch the cards' values back to their original position. The following code already fulfills such a purpose. To avoid explicit usage of the loop, I wonder whether I can achieve a similar effect if I use the vectorization function with packages from tidyverse family, e.g. pmap or related function within the package purrr?

# 1. data generation ------------------------------------------------------
rm(list=ls())
vect<-matrix(round(runif(20),2),nrow=5)
colnames(vect)<-paste0('card',1:4)

order<-rbind(c(2,3,4,1),c(3,4,1,2),c(1,2,3,4),c(4,3,2,1),c(3,4,2,1))
colnames(order)=paste0('pos',1:4)
dat<-data.frame(vect,order,stringsAsFactors = F)

# 2. data swap ------------------------------------------------------------
for (i in 1:dim(dat)[1]){
  orders=dat[i,paste0('pos',1:4)]
  card=dat[i,paste0('card',1:4)]
  vec<-card[order(unlist(orders))]
  names(vec)=paste0('deck',1:4)
  dat[i,paste0('deck',1:4)]<-vec
}
dat



1

1 Answers

3
votes

You could use pmap_dfr :

card_cols <- grep('card', names(dat))
pos_cols <- grep('pos', names(dat))

dat[paste0('deck', seq_along(card_cols))] <- purrr::pmap_dfr(dat, ~{
    x <- c(...)
    as.data.frame(t(unname(x[card_cols][order(x[pos_cols])])))
})
dat

#  card1 card2 card3 card4 pos1 pos2 pos3 pos4 deck1 deck2 deck3 deck4
#1  0.05  0.07  0.16  0.86    2    3    4    1  0.86  0.05  0.07  0.16
#2  0.20  0.98  0.79  0.72    3    4    1    2  0.79  0.72  0.20  0.98
#3  0.50  0.79  0.72  0.10    1    2    3    4  0.50  0.79  0.72  0.10
#4  0.03  0.98  0.48  0.06    4    3    2    1  0.06  0.48  0.98  0.03
#5  0.41  0.72  0.91  0.84    3    4    2    1  0.84  0.91  0.41  0.72

One thing to note here is to make sure that the output from pmap function does not have original names of the columns. If they have the original names, it would reshuffle the columns according to the names and output would not be in correct order. I use unname here to remove the names.