How to put a wordcloud in a grob?

旧街凉风 提交于 2019-12-06 12:13:13

问题


I've created a simple wordcloud:

require(wordcloud)    
words <- c('affectionate', 'ambitious', 'anxious', 'articulate', 'artistic', 'caring', 'contented', 'creative', 'cynical', 'daring', 'dependable', 'easygoing', 'energetic', 'funny', 'generous', 'genuine', 'goodlistener', 'goodtalker', 'happy', 'hardworking', 'humerous', 'impulsive', 'intelligent', 'kind', 'loyal', 'modest', 'optimistic', 'outgoing', 'outrageous', 'passionate', 'perceptive', 'physicallyfit', 'quiet', 'rational', 'respectful', 'romantic', 'shy', 'spiritual', 'spontaneous', 'sweet', 'thoughtful', 'warm')
freqs <- c(134, 53, 0, 5, 0, 247, 0, 78, 0, 0, 134, 178, 79, 344, 63, 65, 257, 0, 109, 113, 0, 0, 107, 51, 199, 24, 67, 232, 0, 109, 24, 28, 29, 2, 105, 70, 0, 35, 64, 156, 66, 45)
wordcloud(words, freqs)

I would like to put this into a "grob" so that I can arrange it with several other plots using grid.arrange() in the gridExtra package:

require(ggplot2)
p1 <- qplot(1:10, rnorm(10), colour = runif(10))
require(gridExtra)
grid.arrange(p1, my.wordcloud)

I understand that my wordcloud must be a "grob" to do this, but I don't understand how to make this so. I tried using the grob() function in the gridExtra package, but this didn't work. Suggestions?


回答1:


It shouldn't be that difficult to adapt the code in wordcloud to construct the data need to fill in a text.grob in grid. The wordcloud code sends x, y, text and rot values to the base text function after a window with limits of 0,0 and 1, 1 is specified.

I needed to add this before the for-loop:

textmat <- data.frame(x1=rep(NA, length(words)), y1=NA, words=NA_character_, 
                       rotWord=NA, cexw=NA, stringsAsFactors=FALSE )

This at the end of the for-loop:

 textmat[i, c(1,2,4,5) ] <-  c(x1=x1, y1=y1, rotWord=rotWord*90, cexw = size[i] )
 textmat[i, 3] <- words[i]

And needed to amend the call to .overlap, because it is apparently not exported:

if (!use.r.layout) 
         return(wordcloud:::.overlap(x1, y1, sw1, sh1, boxes))

And I returned it invisibly after the loop was complete:

return(invisible(textmat[-1, ]))  # to get rid of the NA row at the beginning

After naming it wordcloud2:

> tmat <- wordcloud2(c(letters, LETTERS, 0:9), seq(1, 1000, len = 62))
> str(tmat)
'data.frame':   61 obs. of  5 variables:
 $ x1     : num  0.493 0.531 0.538 0.487 ...
 $ y1     : num  0.497 0.479 0.532 0.475 ...
 $ words  : chr  "b" "O" "M" ...
 $ rotWord: num  0 0 0 0 0 0 0 0 0 ...
 $ cexw   : num  0.561 2.796 2.682 1.421 ...

draw.text <- function(x,y,words,rotW,cexw) {
     grid.text(words, x=x,y=y, rot=rotW, gp=gpar( fontsize=9*cexw)) }

for(i in 1:nrow(tmat) ) { draw.text(x=tmat[i,"x1"], y=tmat[i,"y1"], 
                                    words=tmat[i,"words"], rot=tmat[i,"rotWord"], 
                                    cexw=tmat[i,"cexw"]) }

As suggested:

 with(tmat, grid.text(x=x1, y=y1, label=words, rot=rotWord, 
                      gp=gpar( fontsize=9*cexw)) }  # untested



回答2:


you can use gridBase package but with a clever viewport. here I am using vpStack to get the good dimensions.

par(mfrow=c(1, 2))
wordcloud(words, freqs)
plot.new()              
vps <- baseViewports()
p <- qplot(1:10, rnorm(10), colour = runif(10))
print(p,vp = vpStack(vps$figure,vps$plot))

EDIT Use knitr if you want just to generate a pdf.

Another option if you want just to create a pdf you can use Knitr. Mixing grid and base graphics is really simple. Latex will do the job for you. Fo example, the above result can be obtained by this chunk.

<<mixgridwithggplot, fig.show='hold',out.width='.5\\linewidth'>>=
wordcloud(words, freqs)
qplot(1:10, rnorm(10), colour = runif(10))
@

I am pretty sure that knitr can create the png of the 2 plots in a single png behind the code.



来源:https://stackoverflow.com/questions/15584105/how-to-put-a-wordcloud-in-a-grob

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!