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 '20 at 7:59
  • $\begingroup$ Please answer xzczd's question. $\endgroup$ – J. M.'s ennui Aug 6 '20 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 '20 at 1:59
  • $\begingroup$ Then if 2nd list is {"O", "I", "E"}, how should the venn diagram be drawn? $\endgroup$ – xzczd Aug 10 '20 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 '20 at 13:48
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, privacy policy and cookie policy

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