# How to optimize bin counts with weighted data using multiple lists?

I am trying to sort elements in multiple lists into buckets with weighted data. I can do the single-list case based on a previous question. Specifically, the code under Update in the first answer.

data = {1, 2, 3, 4, 5, 6, 7, 10};
bins = {0, 2, 4, 6, 8, 10};
weights = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0};

With[{ranges = Partition[bins, 2, 1]},
Total@Pick[weights,
BitXor[UnitStep[Subtract[data, #1]],
UnitStep[Subtract[data, #2]]], 1] & @@@ ranges]


which gives the following output: {0.1, 0.5, 0.9, 1.3, 0}

Now, I'm trying to generalise to the following input:

data = {{1, 2, 3, 4, 5, 6, 7, 10}, {3, 5, 6}};
bins = {0, 2, 4, 6, 8, 10};
weights = {{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0}, {0.4, 0.6, 0.5}};


I can't use the same code, because Pick does not treat each list sequentially. However, I can get the desired result using this code (where I make it take the first and second list separately:

With[{ranges = Partition[bins, 2, 1]},
Total@Pick[weights[[1]],
BitXor[UnitStep[Subtract[data, #1]],
UnitStep[Subtract[data, #2]]][[1]], 1] & @@@ ranges]

With[{ranges = Partition[bins, 2, 1]},
Total@Pick[weights[[2]],
BitXor[UnitStep[Subtract[data, #1]],
UnitStep[Subtract[data, #2]]][[2]], 1] & @@@ ranges]


{0.1, 0.5, 0.9, 1.3, 0} {0, 0.4, 0.6, 0.5, 0}

But I want to generalise to a large number of lists now. I tried a loop but when i generalise to a loop it does not work:

For[i = 1, 2, i++,
With[{ranges = Partition[bins, 2, 1]},
Total@Pick[weights[[i]],
BitXor[UnitStep[Subtract[data, #1]],
UnitStep[Subtract[data, #2]]][[i]], 1] & @@@ ranges]
]


How can I generalise it cleanly?

• Don't use For. The output of For is Null, so you can only generate output with side effects (e.g. Print, or assigning output to a variable). – Carl Woll Jun 12 '19 at 3:29

Given wBinCountsLeft from the linked answer, repeated below:

wBinCountsLeft[data_, weights_, bins_] := With[{ranges=Partition[bins,2,1]},
Total @ Pick[
weights,
BitXor[UnitStep[Subtract[data, #1]], UnitStep[Subtract[data, #2]]],
1
]& @@@ ranges
]


you can just use MapThread:

MapThread[
wBinCountsLeft[##, bins]&,
{data, weights}
]


{{0.1, 0.5, 0.9, 1.3, 0}, {0, 0.4, 0.6, 0.5, 0}}