Search code examples
rdiagonalpermute

R diagonal matrix error


I have the following type of dataframe

   A    B   C   D
   1    0   1   10
   0    2   1   15
   1    1   0   11

I would like the following output

    A   B   C   D
    1   0   1   10
    1   1   0   11
    0   2   1   15

I have tried this code

 require(permute)
 z <- apply(permute::allPerms(1:nrow(DF)), 1, function(x){
  mat <- as.matrix(DF,2:ncol(DF)])
 if(all(diag(mat[x,]) == rep(1,nrow(DF)))){
 return(df[x,])} })

I am unable to get the desired output.
(Link for the above code- Arrange data frame in a specific way)

I request someone to guide me. The dataframe is a small sample but I have a huge one with a similar structure.


Solution

  • The following will work so long as there is at least one 1 in every suitable column. It's deterministic so will always just find the first 1 and swap that with the number in the diagonal position. But no combinatorial explosion. Perhaps someone can find a more elegant (or vectorised) solution???

    fn<- function(colm){
      i1<-match(1, colm)
      colm[i1]<- colm[i]
      colm[i]<-1
      return(colm)
    }
    
    
    for(i in 1:nrow(DF))
    {
      DF[,i]=fn(DF[,i])
    
    }
    

    EDIT

    Although this answer was accepted (so I cannot delete) when rereading it I don't think it does quite what you asked...

    The folowing code should fix this answer..

    DF<-read.table(text="A    B   C   D
    13   0   0   1
    1    0   1   10   
    0    2   1   15
    1    1   0   11", header=T)
    
    rem<-1:nrow(DF)
    
    
    for(i in 1:nrow(DF))
    {
      temp<-DF[i,]
      any1<-intersect(rem, which(DF[,i]==1))
      best1<-which.min(rowSums(DF[any1,]==1))
      firsti<-any1[best1]
      DF[i,]<-DF[firsti,]
      DF[firsti,]<-temp
      rem<-setdiff(rem, i)
    
    }
    DF
       A B C  D
    1  1 0 1 10
    2  1 1 0 11
    3  0 2 1 15
    4 13 0 0  1
    

    My apologies for confusion.