# Plot a histogram according to a set of rules using data from two tables

Let's say I have two Tables A={1.0,2.3,1.5,3.0,1.1,} , B={2,10,3,1,0} and I'd like to plot a histogram in the following way:

1. Divide the range of values of A into N bins of equal length (Max[A]-Min[A])/N.
2. There will be some number of "points" (number of corresponding entries of A) in each bin. Count the number of points in each of the bins for which the corresponding entries of B lie between some values minB and maxB.
3. Plot the resulting distribution of points in the bins.

Let's see how it works with the data given.

Max[A]=3.0, Min[A]=1.0, choose N = 2 (the choice is compeletly arbitrary). The width of the bin is 1. The first bin has three "points", because the values A[[1]], A[[3]] and A[[5]] lie between 1.0 and 2.0. The second bin has two "points", because the values A[[2]] and A[[4]] lie between 2.0 and 3.0.

Now, choose minB=1, maxB=3 (again, arbitrarily). Then, out of three "points" in the first bin only i=1 and i=3 work, but not i=5, because the corresponding value of B[[5]] is outside of the closed interval $[minB,maxB]$. Out of two "points" in the second bin only i=4 works, but not i=2, because the corresponding value of B[[2]] is outside of the closed interval $[minB,maxB]$.

Thus the distribution is such that there are two points in the first bin and one point in the second bin.

How do I plot this histogram given A and B?

UPDATE: The problem arose while simulating the production of a neutrino beam. In the actual problem A are energies of the neutrinos and B are off-axis angles. I faked A and B to make it look simpler. This is the first time I'm using Mathematica in my research, so it takes hours to figure out things that other people can do in 2 minutes.

UPDATE2 Some possible data and corresponding outputs.

DATA: A={1,2,3,4,5} , B={1,2,3,4,5}, N=2, minB=1, maxB=3, $bin1=[1,3)$, $bin2=[3,5]$ (note the open and closed intervals).

OUTPUT: bin1={2 points}, bin2={1 point}.

DATA: A={1,2,3,4,5} , B={1,2,3,4,5}, N=4, minB=1, maxB=3, $bin1=[1,2)$, $bin2=[2,3)$, $bin3=[3,4)$, $bin4=[4,5]$ (note the open and closed intervals).

OUTPUT: bin1={1 points}, bin2={1 point}, bin3={1 point}, bin4={0 points}.

• You should consider less inlined code, which makes evaluation cumbersome. Larger, separated code blocks are more convenient. Jun 7, 2015 at 7:48
• I deleted my answer as I'm confused by your example BinLists[A, (maxA - minA)/Length[A]] is a possible starting point, then possibly followed by usage of Select and Position in some way. Jun 7, 2015 at 7:51
• @Histograms, what exactly are you confused about? Jun 7, 2015 at 8:07
• @Physicsworks I updated my answer , I think I have it now. If you provide the expected result for larger data (A,B) and a larger bin-count, I could verify it or correct it. Jun 7, 2015 at 9:22

New answer using BinLists

A = {1.0, 2.3, 1.5, 3.0, 1.1};
B = {2, 10, 3, 1, 0};
nbins = 2;
AIdx = Transpose[{A, Range[Length[A]]}];

(* AIdx contains {{{1., 1}, {1.5, 3}, {1.1, 5}}, {{2.3, 2}, {3., 4}}}
corresponding to
{{A[[1]],A[[3]],A[[5]]},
{A[[2]],A[[4]]}} as value/index pairs *)

{minA, maxA} = {Min[A], Max[A]};
{minB, maxB} = {1, 3};
firstHistIndexed = Flatten[#, 1] & /@ BinLists[AIdx, (maxA - minA)/(nbins - 1), 1];

finalHist =
Function[{sub},
Select[sub, minB <= B[[#[[2]]]] <= maxB &][[All, 1]]] /@ firstHistIndexed

(* Results: {{1., 1.5}, {3.}}  *)

finalHistCounts = Length /@ finalHist

(* Results: {2, 1}  *)


Ok, please clarify if this works. First it takes A and creates pairs of elements with their index. Then it bins these by their value (index kept in second position). You can replace (maxA-minA)/(nbins-1) with a different bin width if you want.

Then from each {value,index} pair in the binning of A, it finds elements of B (using the index) which fall into the range minB,maxB, it does this for all bins. Lastly we remove indices which you no longer need with [[All,1]]. The finalHistCounts is the number of elements of A in some bin of A that also have elements b of B with the same index and this b in B is in the minB,maxB range.

• I haven't got the plot (#3) yet, I need to sleep :P Jun 7, 2015 at 9:50
• I've added some data for you to check. Could you add a code that makes a histogram? Jun 7, 2015 at 17:15

Does something like this help?

A = {1.0, 2.3, 1.5, 3.0, 1.1};
B = {2, 10, 3, 1, 0} ;

minB = 1;
maxB = 3;

Histogram[Pick[A, minB <= # <= maxB & /@ B], 2]


UPDATE: This part does the filtering:

filteredA = Pick[A, minB <= # <= maxB & /@ B]


I assumed the binning was straightforward and didn't try to make it pretty. Here's a better job (but not a general solution):

Histogram[filteredA, {{1, 2, 3 + 10^-6}}, Ticks -> {Range[1, 3], Range[0, 2]}]


Notice I added a small amount the upper bound of the final bin in order to capture the largest observation. This is an issue when you have observations on the bin boundaries.

• Thanks, but the first bin should go from Min[A] to (Max[A]+Min[A])/2 and the second from (Max[A]+Min[B])/2 to Max[A]. Without this, I can't tell whether your neat method works or not. Jun 7, 2015 at 16:51
• @Physicsworks I've addressed that (at least partially) in the edit to my answer. Depending on your data, you may not have the issue with observations that equal bin boundaries.
– mef
Jun 7, 2015 at 19:03