6
$\begingroup$

Question

Suppose you have two sets of data where each value has an associated label of some kind and for whatever reason you wish to histogram them. How can you use Tooltip to tell you the contents of the bin and which set they originate from. Obviously this is not meant for excessively large datasets.

Example Data

(*make data*)
a = RandomInteger[10, 10];
b = RandomInteger[10, 10];

(*make labels*)
labels = RandomChoice[Alphabet[], 20];

(*make it explicit in the label which group data came from*)
aLabels = StringJoin["a: ", #] & /@ labels[[;; 10]]
bLabels = StringJoin["b: ", #] & /@ labels[[11 ;;]]

(*tooltip time*)
c = Tooltip[#1, #2] & @@@ Partition[Riffle[a, aLabels], 2];
e = Tooltip[#1, #2] & @@@ Partition[Riffle[b, bLabels], 2];

(*plot time*)
Histogram[{c, e}]

And you only get one label per bin :(

$\endgroup$
2
$\begingroup$

Cool question. I can find a way to get Histogram to produce the correct tooltip internally, so I've resorted to a little formatting outside, then pointing LabelingFunction to the correctly formatted labels.

First I need to get the list of data points in each histogram bin:

{bins, vals} = HistogramList[a];
{aList, bList} = BinLists[#, {bins}] & /@ {a, b}

{{{4, 0, 4, 0, 2}, {7, 5, 9, 9}, {10}}, {{3, 0, 1, 2}, {5, 6, 5, 7, 7}, {10}}}

Then I use these lists to split the data point labels into the same list structure (there may be a more elegant / efficient way to do this):

labelLists = Function[{ds}, 
    Flatten[Pick[ds[[2]], ds[[1]], #] & /@ Union[#]] & /@ ds[[3]]
  ] /@ Transpose[{{a, b}, {aLabels, bLabels}, {aList, bList}}]

{{{"a: a", "a: x", "a: e", "a: f", "a: v"}, {"a: e", "a: b", "a: b", "a: s"}, {"a: h"}}, {{"b: h", "b: t", "b: s", "b: f"}, {"b: c", "b: o", "b: s", "b: c", "b: v"}, {"b: e"}}}

In this format we can use the second argument (#2) to LabelingFunction to access the correct labels to show for a given histogram bar:

Histogram[{a, b}, {bins}, 
 LabelingFunction -> 
  (Placed[TableForm@{labelLists[[1 ;; #2[[1]], #2[[2]]]]}, Tooltip] &)
]

The extra jiggery-pokery in there (the 1;;#2[[1]] etc) is so that overlapping bars display correctly:

enter image description here enter image description here

$\endgroup$
  • $\begingroup$ very nice! Is there a way to possible make it a more like a table? $\endgroup$ – SumNeuron Oct 18 '16 at 14:08
2
$\begingroup$

The example data you gave has a highly overlapped area. Your real example might not have the same signature, but I would think that PairedHistogram might be a better visualization for the case. Anyway, no matter it is PairedHistogram or Histogram, you can use the customizability of ChartElementFunction to create your own histogram bars. The arguments that get fed in the ChartElementFuncion contain the information of data in each bin.

Here is an example:

f[{x_, y_}, data_, r__] := Tooltip[Rectangle @@ Transpose[{x, y}], data]
a = RandomInteger[10, 10];
b = RandomInteger[10, 10];
PairedHistogram[a, b, ChartElementFunction -> f]

then you can format the list however you want. There are a lot of ways to format lists in WL. Look up TableForm and there are related functions in the bottom of the doc.

enter image description here

$\endgroup$
  • $\begingroup$ Thank you for your answer. PairedHistogram has its purpose, e.g. comparing two similar but distinct distributions. However overlaying can be nice to show similarly. The data from the example were random integers in [1,10] so naturally they overlapped a lot :) I was also able to get Tooltip to display the list, which is sufficient for certain purposes, but it is much nicer to have formatting :D $\endgroup$ – SumNeuron Oct 27 '16 at 4:22

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.