0

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.

Raghavan vmvs
  • 1,213
  • 1
  • 10
  • 29

1 Answers1

1

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.

Stephen Henderson
  • 6,340
  • 3
  • 27
  • 33
  • @ Stephen Henderson. Sir. the combinatorial explosion will slow down the system time. If i am correct – Raghavan vmvs Mar 02 '18 at 10:57
  • 1
    yes on 10000 columns a permute solution will not work in time or memory. If you want it slightly more random then you could replace the match line with `sample(which(colm==1),1)` and it will pick a random 1 if more than one 1 exists. – Stephen Henderson Mar 02 '18 at 11:10