corybrunson / ggalluvial

ggplot2 extension for alluvial plots
http://corybrunson.github.io/ggalluvial/
GNU General Public License v3.0
497 stars 34 forks source link

Data is not in a recognized alluvial form #99

Closed SteveBrouwer closed 1 year ago

SteveBrouwer commented 2 years ago

Hi I have tried to replicate your alluvial plot for the Majors data set (all the others work with my data but not this one). please could you tell me what the issue could be. thanks in advance. my code follows, and for reference your code that i've replicated is below

library(alluvial) library(ggalluvial)

tmp<-data.frame(vessel_home_flag=rep(c(rep(1,4),rep(2,10), rep(3,6)),5), yy_qt = c(rep(c("2015_Q1","2015_Q2","2015_Q3","2015_Q4"), 5), rep(c("2016_Q1","2016_Q2","2016_Q3","2016_Q4"), 5), rep(c("2017_Q1","2017_Q2","2017_Q3","2017_Q4"), 5), rep(c("2018_Q1","2018_Q2","2018_Q3","2018_Q4"), 5), rep(c("2019_Q1","2019_Q2","2019_Q3","2019_Q4"), 5)), charter_state=c(rep("NZ",2),rep("SB",6), rep("VU",4), rep("SB",2), rep("FJ",6), rep("SB",8), rep("VU",4), rep("SB",2), rep("FJ",6), rep("SB",10), rep("VU",2), rep("SB",2), rep("FJ",6), rep("SB",6), rep("VU",6), rep("FJ",8), rep("SB",4), rep("VU",2), rep("FJ",14)))

tmp$yy_qt<-factor(tmp$yy_qt) head(tmp) class(tmp$vessel_home_flag) class(tmp$charter_state) class(tmp$yy_qt)

is_alluvia_form((tmp), axes = 1:3, silent = TRUE) ggplot(tmp, aes(x = yy_qt, stratum = charter_state, alluvium = vessel_home_flag, fill = charter_state, label = charter_state)) + scale_fill_brewer(type = "qual", palette = "Set2") + geom_flow(stat = "alluvium", lode.guidance = "frontback", color = "darkgray") + geom_stratum() + theme(legend.position = "bottom") + ggtitle("Charters across years")

data(majors) majors$curriculum <- as.factor(majors$curriculum) ggplot(majors, aes(x = semester, stratum = curriculum, alluvium = student, fill = curriculum, label = curriculum)) + scale_fill_brewer(type = "qual", palette = "Set2") + geom_flow(stat = "alluvium", lode.guidance = "frontback", color = "darkgray") + geom_stratum() + theme(legend.position = "bottom") + ggtitle("student curricula across several semesters")

Description of the issue

If this is a bug, please explain the behavior you want versus the behavior you get, and feel free to add any additional comments.

If this is not a bug, please just explain the issue as you see fit!

Reproducible example (preferably using reprex::reprex())

If this is a bug, please provide as small an example as you can that reproduces it.

If this is not a bug, feel free to drop this section!

corybrunson commented 2 years ago

Hi @SteveBrouwer and thank you for the clarity of the issue!

I believe the confusion arises from a mismatch between the structural check is_alluvia_form() and the aesthetic mappings in aes(). Data in what i've called "alluvia form" are ready to be plotted using axis aesthetic, not key–value–id aesthetics. The check passed, but here's the plot with the corresponding aesthetic mapping:

ggplot(tmp,
       aes(axis1 = vessel_home_flag, axis2 = yy_qt, axis3 = charter_state,
           fill = charter_state, label = charter_state)) +
  scale_fill_brewer(type = "qual", palette = "Set2") +
  geom_flow(stat = "alluvium", lode.guidance = "frontback",
            color = "darkgray") +
  geom_stratum() +
  theme(legend.position = "bottom") +
  ggtitle("Charters across years")

A plot is successfully rendered, but i'm certain that it's not the one you want.

The aesthetic mapping you use (x, stratum, and alluvium) is for data in what i've called "lodes form", and here's the corresponding structural check:

is_lodes_form((tmp), key = yy_qt, value = charter_state, id = vessel_home_flag)

It fails with the message that the data contain duplicate id–axis pairings, meaning in this case that a single vessel_home_flag appears twice at some x, maybe more. (A single alluvium cannot pass through the same axis twice.) This will need to be resolved, at which point the check should pass and the plot should render.

I hope this helps! Do let me know if not.

In future, this would be a good question to post on StackOverflow, so that others who encounter the same problem will be better able to find a solution.