Additional methods using WeightedData
, EmpiricalDistribution
, GatherBy
and SparseArray
:
{weights,classes} = weightsPerclass = {{1, 0.2, .3, .4, .1, .3, .9, 0}, {1, 2, 3, 1, 3, 1, 1, 5}};
WeightedData
wd = WeightedData[classes, weights];
The property "EmpiricalPDF"
almost gives what we need
wd["EmpiricalPDF"]
(* {{1,2,3,5},{0.8125,0.0625,0.125,0.}} *)
except that it has to be de-normalized by Total[weights]
:
{First@# , Total[weights] Last@#} &@wd["EmpiricalPDF"]
(* {{1,2,3,5},{2.6,0.2,0.4,0.}} *)
Defining a function you can get the result in one step:
wdF = With[{p = WeightedData[#2, #1]["EmpiricalPDF"], w = Total @ #}, {1, w} p] &;
wdF[weights, classes]
(* {{1,2,3,5},{2.6,0.2,0.4,0.}} *)
EmpiricalDistribution
ed = EmpiricalDistribution[Rule @@ weightsPerclass];
ed["Domain"]
(* {1,2,3,5} *)
Total[weights] ed["Weights"]
(* {2.6,0.2,0.4,0.} *)
{%%, %}
(* {{1, 2, 3, 5}, {2.6, 0.2, 0.4, 0.}} *)
You can also define a function that returns the desired output in one step:
ClearAll[wedF]
wedF = With[{d = EmpiricalDistribution[# -> #2], w = Total@#}, {d["Domain"], w d["Weights"]}] &;
wedF[weights, classes]
(* {{1, 2, 3, 5}, {2.6, 0.2, 0.4, 0.}} *)
GatherBy
ClearAll[gthrBy];
gthrBy = Transpose[{Last@First@#, Total[First /@ #]} & /@ GatherBy[Transpose@#, Last]] &;
gthrBy@weightsPerclass
(* {{1,2,3,5},{2.6,0.2,0.4,0}} *)
SparseArray
System`SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" ->Total}];
sa = SparseArray[classes -> weights];
System`SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> First}];
{Flatten[sa["NonzeroPositions"]], sa["NonzeroValues"]}
(* {{1,2,3,5},{2.6,0.2,0.4,0}} *)
See also: Optimizing 2D binning code and Fast 2D binning algorithm
GroupBy - Version 10
Through[{Keys,Values}[GroupBy[Transpose@weightsPerclass,Last -> First, Total]]]
(* {{1,2,3,5}, {2.6,0.2,0.4,0}} *)