This is the a list of set.

data = {{"A"}, {"J"}, {"Q"}, {"G", "H"}, {"I", "O"},
  {"B", "C", "E", "F", "K", "N", "P"},
  {"B", "C", "D", "E", "F", "K", "L", "M", "P"}}

If the name order from left to right is roughly A O I L D M E B C P K F N J H G Q, how to draw one-line Venn diragram like these?

Ps: Because the elements in the same set need to be gathered together, some adjustments may be needed to the position of the name. In this example, P K F is adjusted to F P K.

enter image description here

The approximate style(not using these data) is as follows In VCC

  • 2
    $\begingroup$ If the first sublist is {"A", "Q"}, how should the venn diagram be drawn? $\endgroup$
    – xzczd
    Aug 5, 2020 at 7:59
  • $\begingroup$ Please answer xzczd's question. $\endgroup$ Aug 6, 2020 at 13:38
  • $\begingroup$ @xzczd Since the data and reference positions are both generated by another program and they have roughly the same index order, this will not happen. Therefore, the first sublist is {"A", "Q"} will not happen $\endgroup$
    – partida
    Aug 10, 2020 at 1:59
  • $\begingroup$ Then if 2nd list is {"O", "I", "E"}, how should the venn diagram be drawn? $\endgroup$
    – xzczd
    Aug 10, 2020 at 2:37
  • $\begingroup$ @xzczd Oh, the plot could not be drawn. Assuming the data can make a diagram of one-line, the question I ask is valid, so this visualization may not be very useful. $\endgroup$
    – partida
    Aug 10, 2020 at 13:48

2 Answers 2

ref = StringSplit["A O I L D M E B C P K F N J H G Q"];

pos = PositionIndex[ref];

sorteddata = SortBy[pos@*First][SortBy[pos] /@ data];

Graphics[{Text[Style[#, 32], Append[pos@#, 0]] & /@ ref, 
  MapThread[{ Opacity[.5], #2, Disk[Append[Mean[pos /@ #], 0], {Length[#]/2, 1}]} &, 
    {sorteddata, ColorData[97] /@ Range[Length@data]}]}]

enter image description here


Graphics[{Text[Style[#, FontSize -> Scaled[.05]], Append[pos@#, 0]] & /@ ref, 
  MapThread[{ Opacity[.5], #2, CapForm["Round"], 
     AbsoluteThickness[35], Line[Thread[{Flatten[MinMax[pos /@ #]], 0}]]} &, 
   {sorteddata, ColorData[97] /@ Range[Length@data]}]}, 
  ImageSize -> 600]

enter image description here


Here's one way, which wraps elements in nested colored Frames depending on their set membership. It's not the prettiest, but it's easy and handles non-contiguous intersections straightforwardly.

data = {{"A"}, {"J"}, {"Q"}, {"G", "H"}, {"I", "O"}, {"B", "C", "E", 
   "F", "K", "N", "P"}, {"B", "C", "D", "E", "F", "K", "L", "M", "P"}};

elements = "A O I L D M E B C P K F N J H G Q" // StringSplit;

colors = AssociationThread[
  data -> Map[ColorData[1], Range@Length@data]];

  Function[{element, memberships},
   Fold[Framed[#1, Background -> Lighter[#2], FrameStyle -> #2] &, 
    element, memberships]
  AssociationMap[Select[data, MemberQ[#]] & /* Map[colors], 

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.