In all examples I can find for Sankey/ Alluvial diagrams I see the links come together at the node in such a way that the size of the node is the sum of all the links connecting to it. However, I would like to vizualize a matching procedure, in which 2 databases are matched, into 3 new datasets (A: the data from dataset 1, that could not be matched; B: the data that could be matched between the 2 datasets; and C: the data from dataset 2, that could not be matched).
If I draw a super simple version of this in paint, it looks something like this:
Is there a way to do this in R, python, or D3JS? Preferably in the R package networkD3 ot ggplot, but any software is acceptable.
In my real data, there will be multiple steps of matching and more than 2 datasets, that is why I want to implement this in R, python, or JS and not make an oneof version in Adobe.
Please, this is a labelled version of the plot, in which 75 from both A and B 'connect' together to D. So that A + B > C + D + E
import pandas as pd
import plotly.graph_objects as go
import numpy as np
# two data sets with some overlap...
df1 = pd.DataFrame({"key":range(0,100)})
df2 = pd.DataFrame({"key":range(25, 175)})
# calculate overlap rows
o1 = df1["key"].isin(df2["key"]).value_counts()
o2 = df2["key"].isin(df1["key"]).value_counts()
# prep overlap rows into structure ready for sankey figure
df = pd.DataFrame([{"source":str(len(df1)), "target":"a" + str(o1[False]), "value":o1[False]},
{"source":str(len(df1)), "target":"b" + str(o1[True]), "value":o1[True]/2},
{"source":str(len(df2)), "target":"b" + str(o2[True]), "value":o2[True]/2},
{"source":str(len(df2)), "target":"c" + str(o2[False]), "value":o2[False]},
])
# build sankey figure
nodes = np.unique(df[["source","target"]], axis=None)
nodes = pd.Series(index=nodes, data=range(len(nodes)))
go.Figure(
go.Sankey(
node={"label": nodes.index},
link={
"source": nodes.loc[df["source"]],
"target": nodes.loc[df["target"]],
"value": df["value"],
},
)
)