简体   繁体   中英

How to display lists side-by-side in R - a "cbind" for lists?

I am looking to use my screen real estate to look at several simple lists side by side. I'm not trying to combine them, a la cbind , but I wouldn't mind if a new intermediate structure were created. Realize, of course, that a list may have many different types of objects, though I will almost guarantee that my lists have the same structures; feel free to insert "NA" or "NULL" if necessary to make things work (or I can figure out how to wrangle that).

Here are three example lists that I would like to try to display side by side:

l1 <- list(e1 = "R", e2 = list("statistics", "visualization"), e3 = 0)
l2 <- list(e1 = "Perl", e2 = list("text processing", "scripting"), e3 = 0)
l3 <- list(e1 = "Matlab", e2 = list("numerical computing", "simulation"), e3 = c("academic - unknown", "professional - unknown"))

If you have a wide monitor, it looks like a waste to see these take up so much vertical room and so little room used on the horizontal access. If these lists were just a little longer, I wouldn't be able to see more than 2 at a time, without reducing to a small font.

If it makes it easier, the e3 entries in l1 and l2 could be "FOSS" , to match the character vectors of l3$e3 , but the real goal is a layout problem in the R console.

Some naive, interface-specific solutions include:

  • Fire up multiple R instances, split screen using GNU screen and CA |
  • Learn ESS, and let the miracle of Emacs solve everything
  • Go back and forth with another text editor (eg Notepad++) and manually migrate blocks of text

The non-naive solutions that I'm trying are:

  • Write these out to a text file. The problem here is working out fixed width spacing. Maybe read.fwf would help. (It's okay to stop with an error if an entry would exceed the allotted space, or to truncate stuff.)
  • Try something with the reshape package.
  • Possibly something involving xlsx , to create a bunch of cells, each with text entries, and then attempt to display a big character matrix.

Are there some other methods that would be more efficient? Again, nothing really needs to be combined as an object, just combined in the visual display.


Update 1. Here is an example using plyr . The results are admittedly quite crude - names of lists and list elements have not been preserved That's not too hard to fix, but I suspect it's possible to do much better than this. I'm okay with printing out the lists as R normally prints them, but separating the window in some way. I have a suspicion that's not easy.

combineLists <- function(manyLists){
    library(plyr)
    newLists <- list()
    for(ixList in 1:length(manyLists)){
        tmpList <- lapply(manyLists[[ixList]], paste, sep = "", collapse = ", ")
        tmpVec  <- as.character(tmpList)
        newLists[[ixList]] <- tmpVec
    }
    newDF   <- t(ldply(newLists))
    return(newDF)
}

combineLists(list(l1, l2, l3))

Combine some capture.output , lapply , gsub and format into a container. Use do.call as a binding agent. Add paste to taste. Let it brew for a while:

sidebyside <- function(..., width=60){
  l <- list(...)
  p <- lapply(l, function(x){
        xx <- capture.output(print(x, width=width))
        xx <- gsub("\"", "", xx)
        format(xx, justify="left", width=width)
      }
  )
  p <- do.call(cbind, p)
  sapply(seq_len(nrow(p)), function(x)paste(p[x, ], collapse=""))
}

This will cure everything:

sidebyside(l1, l2, l3, width=30)

 [1] "$e1                           $e1                           $e1                                              "
 [2] "[1] R                         [1] Perl                      [1] Matlab                                       "
 [3] "                                                                                                             "
 [4] "$e2                           $e2                           $e2                                              "
 [5] "$e2[[1]]                      $e2[[1]]                      $e2[[1]]                                         "
 [6] "[1] statistics                [1] text processing           [1] numerical computing                          "
 [7] "                                                                                                             "
 [8] "$e2[[2]]                      $e2[[2]]                      $e2[[2]]                                         "
 [9] "[1] visualization             [1] scripting                 [1] simulation                                   "
[10] "                                                                                                             "
[11] "                                                                                                             "
[12] "$e3                           $e3                           $e3                                              "
[13] "[1] 0                         [1] 0                         [1] academic - unknown     professional - unknown"
[14] "                                                                                                             "

You could use gplots::textplot :

library(gplots)
textplot(cbind(l1,l2,l3))

It helps to maximise your window first.

That is not a very clean solution, but you could convert the lists to strings, put them in two separate files, and call diff -y (or any similar application) to display the differences between the two files. Provided the structures are very similar, they will be aligned.

cat(capture.output( print(l1) ), sep="\n", file="tmp1")
cat(capture.output( print(l2) ), sep="\n", file="tmp2")
system("diff -y tmp1 tmp2")
    a <- c("a", "b", "c")
    b <- c("1", "2", "3")

    for (i in 1:length(a)){
      cat(paste0(a[i] , " ", b[i]), sep = "\n")}'

Output:
a 1
b 2
c 3

Why not use unlist() ? And cheat them into rows?

for(x in 1:3) { 
print(rbind(unlist(get(paste("l",x,sep="")))))
}

You could set use.names=FALSE if you don't like the e1 e2 etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM