问题
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
andC-A |
- Learn ESS, and let the miracle of Emacs solve everything
- Go back and forth with another text editor (e.g. 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))
回答1:
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] " "
回答2:
You could use gplots::textplot
:
library(gplots)
textplot(cbind(l1,l2,l3))
It helps to maximise your window first.
回答3:
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")
回答4:
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.
来源:https://stackoverflow.com/questions/9213949/how-to-display-lists-side-by-side-in-r-a-cbind-for-lists