From 44c80715ec07d601bca7a86237c985c0e635da95 Mon Sep 17 00:00:00 2001 From: Benedikt Venn Date: Wed, 26 Apr 2023 14:56:51 +0200 Subject: [PATCH 1/5] add map merge #263 --- src/FSharp.Stats/Distributions/Empirical.fs | 53 ++++++++++++++++++++- src/FSharp.Stats/Distributions/Frequency.fs | 31 +++++++++--- src/FSharp.Stats/FSharp.Stats.fsproj | 1 + 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Empirical.fs b/src/FSharp.Stats/Distributions/Empirical.fs index a3737b77..796e0045 100644 --- a/src/FSharp.Stats/Distributions/Empirical.fs +++ b/src/FSharp.Stats/Distributions/Empirical.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Distributions +open FSharp.Stats + /// Represents a probability mass function (map from values to probabilities). module Empirical = open System @@ -183,15 +185,64 @@ module Empirical = ) |> Map.ofSeq |> normalize + + /// Merges two maps into a single map. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. + /// Function to transform values if key is present in both histograms. `histA-value → histB-value → newValue` + /// Empirical distribution A + /// Empirical distribution B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) + /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f + let mergeBy (f: 'value -> 'value -> 'value) (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.mergeBy f histA histB -type EmpiricalDistribution() = + /// Merges two maps into a single map. If a key exists in both maps, the value in histA is superseded by the value in histB. + /// Empirical distribution A + /// Empirical distribution B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (merge a b) is not equal to (merge b a) + /// New frequency map that results from merged maps histA and histB. + let merge (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.merge histA histB + + /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + /// Empirical distribution A + /// Empirical distribution B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (add a b) is not equal to (add b a) + /// New frequency map that results from merged maps histA and histB. Values from keys that are present in both maps are handled by f + let inline add (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.mergeAdd histA histB + +type EmpiricalDistribution() = + /// Creates probability mass function of the input sequence. /// The bandwidth defines the width of the bins the numbers are sorted into. /// Bin intervals are half open excluding the upper border: [lower,upper) static member create(bandwidth: float) = fun (data: seq) -> Empirical.create bandwidth data + + ///// Merges two maps into a single map. If a key exists in both maps, the value in histA is superseded by the value in histB. + ///// Empirical distribution A + ///// Empirical distribution B + ///// When applied to continuous data the bandwidths must be equal! + ///// This function is not commutative! (merge a b) is not equal to (merge b a) + ///// New frequency map that results from merged maps histA and histB. + //static member merge: ((Map<_,float> -> Map<_,float> -> Map<_,float>)) = + // fun histA histB -> + // Empirical.merge histA histB + + ///// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + ///// Empirical distribution A + ///// Empirical distribution B + ///// When applied to continuous data the bandwidths must be equal! + ///// This function is not commutative! (add a b) is not equal to (add b a) + ///// New frequency map that results from merged maps histA and histB. Values from keys that are present in both maps are handled by f + //static member add: ((Map<_,float> -> Map<_,float> -> Map<_,float>)) = + // fun histA histB -> + // Empirical.add histA histB /// Creates probability mass function of the categories in the input sequence. /// A template defines the search space to exclude certain elements or to include elements that are not in the input sequence. diff --git a/src/FSharp.Stats/Distributions/Frequency.fs b/src/FSharp.Stats/Distributions/Frequency.fs index ce0dd232..3b815866 100644 --- a/src/FSharp.Stats/Distributions/Frequency.fs +++ b/src/FSharp.Stats/Distributions/Frequency.fs @@ -2,6 +2,7 @@ namespace FSharp.Stats.Distributions /// Represents a histogram (map from values to integer frequencies). module Frequency = + open FSharp.Stats /// Given the list [a,b,a,c,b,b], produce a map {a:2, b:3, c:1} which contains the count of each unique item in the list let createGeneric list = @@ -66,12 +67,30 @@ module Frequency = | [] -> true issubset (histA |> Map.toList) histB - ///// Subtracts the values histogramA from histogramB - //let subtract (histA:Map<'a,int>) (histB:Map<'a,int>) = - // Map.merge histA histB (fun k (v, v') -> v - v') - ////// Adds the values in histogramA to histogramB - //let add (histA:Map<'a,int>) (histB:Map<'a,int>) = - // Map.merge histA histB (fun k (v, v') -> v + v') + /// Merges two maps into a single map. If a key exists in both maps, the value in histA is superseded by the value in histB. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (merge a b) is not equal to (merge b a) + /// New frequency map that results from merged maps histA and histB. + let merge (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.merge histA histB + /// Merges two maps into a single map. If a key exists in both maps, the value from histB is subtracted from the value of histA. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (subtract a b) is not equal to (subtract b a) + let inline subtract (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.mergeSubtract histA histB + + /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (add a b) is not equal to (add b a) + /// New frequency map that results from merged maps histA and histB. Values from keys that are present in both maps are handled by f + let inline add (histA: Map<_,'value>) (histB: Map<_,'value>) = + Map.mergeAdd histA histB diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 3f71419f..fbd71cb4 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -45,6 +45,7 @@ + From 9bd6c08fa715f9a9f24aa418c79c18e97b2744cb Mon Sep 17 00:00:00 2001 From: Benedikt Venn Date: Wed, 26 Apr 2023 14:57:02 +0200 Subject: [PATCH 2/5] add map merge tests #263 --- .../DistributionsEmpirical.fs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs b/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs index c1a1bd5f..8339db59 100644 --- a/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs +++ b/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs @@ -9,7 +9,6 @@ open TestExtensions [] let empiricalTests = - let mySmallAlphabet = "abcdefghijklmnopqrstuvwxyz" |> Set.ofSeq let myAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |> Set.ofSeq let myAlphabetNum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" |> Set.ofSeq @@ -146,5 +145,48 @@ let empiricalTests = "Empirical.createNominal leads to a wrong PMF map keys" TestExtensions.sequenceEqual(Accuracy.high) expectedValues actualValues "Empirical.createNominal leads to a wrong PMF map values" + let a = + [ + (0.2,12) + (0.0,5) + (-0.1,3) + ] + |> Map.ofList + + let b = + [ + (0.2,-10) + (0.3,2) + (0.0,0) + ] + |> Map.ofList + + testCase "add" <| fun () -> + let expectedKeys,expectedValues = + Map.ofSeq [|(-0.1,3);(0.0,5);(0.2,2);(0.3,2)|] + |> Map.toArray + |> Array.unzip + let actualKeys,actualValues = + Empirical.add a b + |> Map.toArray + |> Array.unzip + Expect.equal expectedKeys actualKeys + "Empirical.add leads to a wrong distribution addition" + Expect.equal expectedValues actualValues + "Empirical.add leads to a wrong distribution addition" + + testCase "merge" <| fun () -> + let expectedKeys,expectedValues = + Map.ofSeq [|(-0.1,3);(0.0,0);(0.2,-10);(0.3,2)|] + |> Map.toArray + |> Array.unzip + let actualKeys,actualValues = + Empirical.merge a b + |> Map.toArray + |> Array.unzip + Expect.equal expectedKeys actualKeys + "Empirical.merge leads to a wrong distribution merge" + Expect.equal expectedValues actualValues + "Empirical.merge leads to a wrong distribution merge" ] From 6e0a7adf51f7331f9303b4245f1d90969b711262 Mon Sep 17 00:00:00 2001 From: Benedikt Venn Date: Wed, 26 Apr 2023 14:57:46 +0200 Subject: [PATCH 3/5] add distribution merge documentation #263 --- docs/Distributions.fsx | 60 +++++++++++++++++++++++++++++++++++++++++ src/FSharp.Stats/Map.fs | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/FSharp.Stats/Map.fs diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index cf3b0cf7..03249b1c 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -816,6 +816,66 @@ categoricalDistribution categoricalDistribution |> GenericChart.toChartHTML (***include-it-raw***) + +(** +### Distribution merging + +You can merge two distributions by using `Empirical.merge`, subroutines like `Empirical.add`, or the generic function `Empirical.mergeBy`. + +Merging two distributions leads to a combined distribution. If keys are present in both distributions the value at `distA` is superseded with +the value at `distB`. + +*) + +let a = + [("k1",1);("k2",3)] + |> Map.ofList + +let b = + [("k2",2);("k3",4)] + |> Map.ofList + +let mergedDist = Empirical.merge a b + +(*** condition: ipynb ***) +#if IPYNB +mergedDist +#endif // IPYNB + +(***hide***) +(sprintf "mergeDist = %A" mergedDist) +(***include-it-raw***) + +(** +Adding two distributions leads to a combined distribution. If keys are present in both distributions the values at `distA` and `distB` are added. +*) + +let addedDist = Empirical.add a b + +(*** condition: ipynb ***) +#if IPYNB +addedDist +#endif // IPYNB + +(***hide***) +(sprintf "addedDist = %A" addedDist) +(***include-it-raw***) + +(** +A custom merging function can be defined: +*) + +let customDist = Empirical.mergeBy (fun valueA valueB -> valueA * valueB) a b + +(*** condition: ipynb ***) +#if IPYNB +customDist +#endif // IPYNB + +(***hide***) +(sprintf "customDist = %A" customDist) +(***include-it-raw***) + (** ## Density estimation *) diff --git a/src/FSharp.Stats/Map.fs b/src/FSharp.Stats/Map.fs new file mode 100644 index 00000000..a42f4813 --- /dev/null +++ b/src/FSharp.Stats/Map.fs @@ -0,0 +1,50 @@ +namespace FSharp.Stats + + +/// Module to strore specialised computations on maps +module Map = + + /// Merges two maps into a single map. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. + /// Function to transform values if key is present in both histograms. `mapA-value → mapB-value → newValue` + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) + /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f + let mergeBy (f: 'value -> 'value -> 'value) (mapA: Map<'key,'value>) (mapB:Map<'key,'value>) = + mapB + |> Map.fold (fun (s: Map<'key,'value>) kB vB -> + let tmp = Map.tryFind kB s + match tmp with + | Some x -> Map.change kB (fun vA -> Some (f x vB)) s + | None -> Map.add kB vB s + ) + mapA + + /// Merges two maps into a single map. If a key exists in both maps, the value in mapA is superseded by the value in mapB. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (merge a b) is not equal to (merge b a) + /// New frequency map that results from merged maps mapA and mapB. + let merge (mapA: Map<'key,'value>) (mapB: Map<'key,'value>) = + mergeBy (fun a b -> b) mapA mapB + + /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is subtracted from the value of mapA. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (subtract a b) is not equal to (subtract b a) + let inline mergeSubtract (mapA: Map<'key,'value>) (mapB: Map<'key,'value>) = + mergeBy (fun a b -> a - b) mapA mapB + + /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (add a b) is not equal to (add b a) + /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f + let inline mergeAdd (mapA: Map<'key,'value>) (mapB: Map<'key,'value>) = + mergeBy (fun a b -> a + b) mapA mapB + + From 21eb2f89de489a614af840b5adf73627abe04731 Mon Sep 17 00:00:00 2001 From: Benedikt Venn Date: Wed, 26 Apr 2023 15:05:55 +0200 Subject: [PATCH 4/5] update merge documentation --- docs/Distributions.fsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 03249b1c..c812d748 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -825,6 +825,8 @@ You can merge two distributions by using `Empirical.merge`, subroutines like `Em Merging two distributions leads to a combined distribution. If keys are present in both distributions the value at `distA` is superseded with the value at `distB`. +Please note, that when handling continuous data, the binning of both input distributions must be identical! + *) let a = From 814ae18f99c67f563e93b7211224b49df8c05e34 Mon Sep 17 00:00:00 2001 From: Benedikt Venn Date: Thu, 27 Apr 2023 14:07:39 +0200 Subject: [PATCH 5/5] add bandwidth test #263 --- docs/Distributions.fsx | 10 ++-- src/FSharp.Stats/Distributions/Empirical.fs | 21 +++++--- src/FSharp.Stats/Distributions/Frequency.fs | 51 ++++++++++++++----- src/FSharp.Stats/Map.fs | 2 +- .../DistributionsEmpirical.fs | 4 +- 5 files changed, 61 insertions(+), 27 deletions(-) diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index c812d748..2bd0ebec 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -825,7 +825,9 @@ You can merge two distributions by using `Empirical.merge`, subroutines like `Em Merging two distributions leads to a combined distribution. If keys are present in both distributions the value at `distA` is superseded with the value at `distB`. -Please note, that when handling continuous data, the binning of both input distributions must be identical! +Please note, that when handling continuous data, the binning of both input distributions must be identical! When using categorical data, +the binning does not matter and the parameter can be set to `true`. + *) @@ -837,7 +839,7 @@ let b = [("k2",2);("k3",4)] |> Map.ofList -let mergedDist = Empirical.merge a b +let mergedDist = Empirical.merge true a b (*** condition: ipynb ***) #if IPYNB @@ -852,7 +854,7 @@ mergedDist Adding two distributions leads to a combined distribution. If keys are present in both distributions the values at `distA` and `distB` are added. *) -let addedDist = Empirical.add a b +let addedDist = Empirical.add true a b (*** condition: ipynb ***) #if IPYNB @@ -867,7 +869,7 @@ addedDist A custom merging function can be defined: *) -let customDist = Empirical.mergeBy (fun valueA valueB -> valueA * valueB) a b +let customDist = Empirical.mergeBy true (fun valueA valueB -> valueA * valueB) a b (*** condition: ipynb ***) #if IPYNB diff --git a/src/FSharp.Stats/Distributions/Empirical.fs b/src/FSharp.Stats/Distributions/Empirical.fs index 796e0045..f9fcfef4 100644 --- a/src/FSharp.Stats/Distributions/Empirical.fs +++ b/src/FSharp.Stats/Distributions/Empirical.fs @@ -187,32 +187,41 @@ module Empirical = |> normalize /// Merges two maps into a single map. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. + /// Is the binwidth equal for both distributions? For nominal data set to true. /// Function to transform values if key is present in both histograms. `histA-value → histB-value → newValue` /// Empirical distribution A /// Empirical distribution B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f - let mergeBy (f: 'value -> 'value -> 'value) (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.mergeBy f histA histB + let mergeBy equalBandwidthOrNominal (f: 'value -> 'value -> 'value) (histA: Map<_,'value>) (histB: Map<_,'value>) = + if equalBandwidthOrNominal then + Map.mergeBy f histA histB + else + failwithf "Not implemented yet. If continuous data shall be merged, bandwidth must be equal. This does not matter for nominal data!" + //ToDo: + // Dissect both distributions and construct a new one based on given bandwidths + // New bandwidth might be double the largest observed bandwidth to not miss-sort any data. /// Merges two maps into a single map. If a key exists in both maps, the value in histA is superseded by the value in histB. + /// Is the binwidth equal for both distributions? For nominal data set to true. /// Empirical distribution A /// Empirical distribution B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (merge a b) is not equal to (merge b a) /// New frequency map that results from merged maps histA and histB. - let merge (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.merge histA histB + let merge equalBandwidthOrNominal (histA: Map<_,'value>) (histB: Map<_,'value>) = + mergeBy equalBandwidthOrNominal (fun a b -> b) histA histB /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + /// Is the binwidth equal for both distributions? For nominal data set to true. /// Empirical distribution A /// Empirical distribution B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (add a b) is not equal to (add b a) /// New frequency map that results from merged maps histA and histB. Values from keys that are present in both maps are handled by f - let inline add (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.mergeAdd histA histB + let inline add equalBandwidthOrNominal (histA: Map<_,'value>) (histB: Map<_,'value>) = + mergeBy equalBandwidthOrNominal (fun a b -> a + b) histA histB type EmpiricalDistribution() = diff --git a/src/FSharp.Stats/Distributions/Frequency.fs b/src/FSharp.Stats/Distributions/Frequency.fs index 3b815866..1825a001 100644 --- a/src/FSharp.Stats/Distributions/Frequency.fs +++ b/src/FSharp.Stats/Distributions/Frequency.fs @@ -51,7 +51,7 @@ module Frequency = if hist.ContainsKey(x) then hist.[x] else - 0 + 0 /// Gets an unsorted sequence of frequencies let frequencies (hist:Map<_,int>) = @@ -61,36 +61,59 @@ module Frequency = let isSubset (histA:Map<_,int>) (histB:Map<_,int>) = let rec issubset (histA:list) (histB:Map) = match histA with - | head::rest -> let k,v = head - let y = frequencyAt histB k - if v > y then false else issubset rest histB + | head::rest -> + let k,v = head + let y = frequencyAt histB k + if v > y then + false + else + issubset rest histB | [] -> true issubset (histA |> Map.toList) histB - /// Merges two maps into a single map. If a key exists in both maps, the value in histA is superseded by the value in histB. + /// Merges two histograms into a single histogram. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. + /// Is the binwidth equal for both frequencies? For nominal data set to true. + /// Function to transform values if key is present in both histograms. `mapA-value → mapB-value → newValue` + /// Frequency map A + /// Frequency map B + /// When applied to continuous data the bandwidths must be equal! + /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) + /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f + let mergeBy equalBandwidthOrNominal f (histA: Map<_,'value>) (histB: Map<_,'value>) = + if equalBandwidthOrNominal then + Map.mergeBy f histA histB + else + failwithf "Not implemented yet. If continuous data shall be merged, bandwidth must be equal. This does not matter for nominal data!" + //ToDo: + // Dissect both frequencies and construct a new one based on given bandwidths + // New bandwidth might be double the largest observed bandwidth to not miss-sort any data. + + /// Merges two histograms into a single histogram. If a key exists in both histograms, the value in histA is superseded by the value in histB. + /// Is the binwidth equal for both frequencies? For nominal data set to true. /// Frequency map A /// Frequency map B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (merge a b) is not equal to (merge b a) /// New frequency map that results from merged maps histA and histB. - let merge (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.merge histA histB + let merge equalBandwidthOrNominal (histA: Map<_,'value>) (histB: Map<_,'value>) = + mergeBy equalBandwidthOrNominal (fun a b -> b) histA histB - /// Merges two maps into a single map. If a key exists in both maps, the value from histB is subtracted from the value of histA. + /// Merges two histograms into a single histogram. If a key exists in both histograms, the value from histB is subtracted from the value of histA. + /// Is the binwidth equal for both frequencies? For nominal data set to true. /// Frequency map A /// Frequency map B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (subtract a b) is not equal to (subtract b a) - let inline subtract (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.mergeSubtract histA histB + let inline subtract equalBandwidthOrNominal (histA: Map<_,'value>) (histB: Map<_,'value>) = + mergeBy equalBandwidthOrNominal (fun a b -> a - b) histA histB - /// Merges two maps into a single map. If a key exists in both maps, the value from mapB is added to the value of mapA. + /// Merges two histograms into a single histogram. If a key exists in both histograms, the value from histA is added to the value of histB. + /// Is the binwidth equal for both frequencies? For nominal data set to true. /// Frequency map A /// Frequency map B /// When applied to continuous data the bandwidths must be equal! - /// This function is not commutative! (add a b) is not equal to (add b a) /// New frequency map that results from merged maps histA and histB. Values from keys that are present in both maps are handled by f - let inline add (histA: Map<_,'value>) (histB: Map<_,'value>) = - Map.mergeAdd histA histB + let inline add equalBandwidthOrNominal (histA: Map<_,'value>) (histB: Map<_,'value>) = + mergeBy equalBandwidthOrNominal (fun a b -> a + b) histA histB diff --git a/src/FSharp.Stats/Map.fs b/src/FSharp.Stats/Map.fs index a42f4813..86d8fef2 100644 --- a/src/FSharp.Stats/Map.fs +++ b/src/FSharp.Stats/Map.fs @@ -5,7 +5,7 @@ module Map = /// Merges two maps into a single map. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. - /// Function to transform values if key is present in both histograms. `mapA-value → mapB-value → newValue` + /// Function to transform values if key is present in both maps. `mapA-value → mapB-value → newValue` /// Frequency map A /// Frequency map B /// When applied to continuous data the bandwidths must be equal! diff --git a/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs b/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs index 8339db59..a1fd55c8 100644 --- a/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs +++ b/tests/FSharp.Stats.Tests/DistributionsEmpirical.fs @@ -167,7 +167,7 @@ let empiricalTests = |> Map.toArray |> Array.unzip let actualKeys,actualValues = - Empirical.add a b + Empirical.add true a b |> Map.toArray |> Array.unzip Expect.equal expectedKeys actualKeys @@ -181,7 +181,7 @@ let empiricalTests = |> Map.toArray |> Array.unzip let actualKeys,actualValues = - Empirical.merge a b + Empirical.merge true a b |> Map.toArray |> Array.unzip Expect.equal expectedKeys actualKeys