0

I need a short R script that can reorganise both large matrices and data.frames into 3 column data.frames. My current script can handle matrices but returns an error message when I input a data.frame. Any advice on how I can force it to handle both classes?

library(FD)

ds<-dummy$abun #a matrix

#reorganize into 3 column data.frame 
q<-rep.int(row.names(ds),ncol(ds))
p<-rep(colnames(ds),each = (nrow(ds)))
ssf<-data.frame(q,p,as.numeric(ds)) 
names(ssf) <- c("site", "species", "freq")

Works fine but I want it to be able to reorganize both matrices and dataframes (i.e.)

ds<-as.data.frame(dummy$abun) #a matrix

#reorganize into 3 column data.frame 
q<-rep.int(row.names(ds),ncol(ds))
p<-rep(colnames(ds),each = (nrow(ds)))
ssf<-data.frame(q,p,as.numeric(ds)) 
names(ssf) <- c("site", "species", "freq")

returns

'Error in data.frame(q, p, as.numeric(ds)) : (list) object cannot be coerced to type 'double'
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
Elizabeth
  • 6,391
  • 17
  • 62
  • 90
  • 1
    Untested, but since the second one is a `data.frame`, `as.numeric` won't have the same effect as it does on a matrix. Try changing that line to `as.numeric(unlist(ds, use.names = FALSE))` and see if that works for you. – A5C1D2H2I1M1N2O1R2T1 Sep 11 '13 at 12:28
  • 1
    Also, it looks like you're just trying to do `setNames(cbind(rownames(ds), stack(as.data.frame(ds))), c("Site", "Freq", "Species"))`. See also `melt` from "reshape2". – A5C1D2H2I1M1N2O1R2T1 Sep 11 '13 at 12:36
  • Thanks, changing the as.numeric() line worked great. Using setNames also works and is shorter but switches the column order from site,species, freq to site, freq, species. @AnandaMahto If you would like to post this as an answer I can accept it. Thanks again. – Elizabeth Sep 11 '13 at 12:53
  • possible duplicate of [Reshaping data.frame from wide to long format](http://stackoverflow.com/questions/2185252/reshaping-data-frame-from-wide-to-long-format) – Ferdinand.kraft Sep 11 '13 at 13:04

1 Answers1

1

Two points:

  1. While as.numeric will create a simple vector from a matrix, it won't do the same for a data.frame. A data.frame is a list of vectors, while a matrix is a vector with a dimensional attribute. As such, an alternative would be to use unlist first:

    as.numeric(unlist(ds, use.names = FALSE))
    
  2. It seems like you're actually just trying to create a "long" form of your data. In this case, explore stack from base R and melt from "reshape2". A possible approach would be:

    out <- cbind(rownames(ds), stack(as.data.frame(ds)))
    names(out) <- c("vector", "of", "names") ## Replace as required :)
    

    or

    library(reshape2)
    out <- melt(as.matrix(ds))
    
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485