ggplot2: create ordered group bar plot - (use reorder)

我只是一个虾纸丫 提交于 2019-12-06 15:18:57

问题


I want to create grouped bar plot while keeping order. If it was single column and not a grouped bar plot use of reorder function is obvious. But not sure how to use it on a melted data.frame.

Here is the detail explanation with code example:

Lets say we have following data.frame:

d.nfl <- data.frame(Team1=c("Vikings", "Chicago", "GreenBay", "Detroit"), Win=c(20, 13, 9, 12))

plotting a simple bar plot while flipping it.

ggplot(d.nfl, aes(x = Team1, y=Win)) + geom_bar(aes(fill=Team1), stat="identity") + coord_flip()

above plot will not have an order and if I want to order the plot by win I can do following:

d.nfl$orderedTeam <- reorder(d.nfl$Team1, d.nfl$Win)
ggplot(d.nfl, aes(x = orderedTeam, y=Win)) + geom_bar(aes(fill=orderedTeam), stat="identity") + coord_flip()

Now lets say we add another column (to original data frame)

d.nfl$points <- c(12, 3, 45, 5)

     Team1 Win points
1  Vikings  20     12
2  Chicago  13      3
3 GreenBay   9     45
4  Detroit  12      5

to generate grouped bar plot, first we need to melt it:

library(reshape2)
> d.nfl.melt <- melt(d.nfl[,c('Team1','Win','points')],id.vars = 1)
> ggplot(d.nfl.melt,aes(x = Team1,y = value)) + geom_bar(aes(fill = variable),position = "dodge", stat="identity") + coord_flip()

above ggplot is unordered.

but how I do ordered group bar plot (ascending manner)


回答1:


This is a non-issue.

The easiest way is to not discard your ordered team in the melt:

d.nfl.melt <- melt(d.nfl,id.vars = c("Team1", "orderedTeam"))

Alternatively, we can use reorder after melting and just only use the Win elements in computing the ordering:

d.nfl.melt$ordered_after_melting = reorder(
    d.nfl.melt$Team1,
    X = d.nfl.melt$value * (d.nfl.melt$variable == "Win")
)

Yet another idea is to take the levels from the original ordered column and apply them to a melted factor:

d.nfl.melt$copied_levels = factor(
    d.nfl.melt$Team1,
    levels = levels(d.nfl$orderedTeam)
)

All three methods give the same result. (I left out the coord_flips because they don't add anything to the question, but you can of course add them back in.)

gridExtra::grid.arrange(
    ggplot(d.nfl.melt,aes(x = orderedTeam, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity"),
    ggplot(d.nfl.melt,aes(x = ordered_after_melting, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity"),
    ggplot(d.nfl.melt,aes(x = copied_levels, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity")
)

As to the easiest, I would recommend just keeping the orderedTeam variable around while melting. Your code seems to work hard to leave it out, it's quite easy to keep it in.




回答2:


The challenge your question presents is how to reorder a factor Team1 based on a subset values in a melted column.

The comments to your question from @alistaire and @joran link to great answers. The tl;dr answer is to just apply the ordering from your original, unmelted data.frame to the new one using levels().

library(reshape2)
#Picking up from your example code:
d.nfl.melt <- melt(d.nfl[,c('Team1','Win','points')],id.vars = 1)
levels(d.nfl.melt$Team1)
#Current order is alphabetical
#[1] "Chicago"  "Detroit"  "GreenBay" "Vikings" 

#Reorder based on Wins (using the same order from your earlier, unmelted data.frame)
d.nfl.melt$Team1 <- factor(d.nfl.melt$Team1, levels = levels(d.nfl$orderedTeam)) #SOLUTION
levels(d.nfl.melt$Team1)
#New order is ascending by wins
#[1] "GreenBay" "Detroit"  "Chicago"  "Vikings" 

ggplot(d.nfl.melt,aes(x = Team1,y = value)) + 
  geom_bar(aes(fill = variable),position = "dodge", stat="identity") + coord_flip()



来源:https://stackoverflow.com/questions/36986699/ggplot2-create-ordered-group-bar-plot-use-reorder

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