Skip to main content

TupleUnionBuilder

Struct TupleUnionBuilder 

Source
pub struct TupleUnionBuilder<S: TupleSummary> { /* private fields */ }
Expand description

Builder for TupleUnion. lg_k defaults to 12, resize_factor to ResizeFactor::X8, p to 1.0.

Implementations§

Source§

impl<S: TupleSummary> TupleUnionBuilder<S>

Source

pub fn new() -> Self

Creates a builder with default settings.

Examples found in repository?
examples/tuple_generic.rs (line 90)
63fn main() {
64    let mut january: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
65    for user in 0..10_000u64 {
66        january.update_u64(
67            user,
68            &Event {
69                revenue_cents: 250 + (user % 100),
70                country: if user % 2 == 0 { "GB" } else { "US" },
71            },
72        );
73    }
74
75    let mut february: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
76    for user in 5_000..15_000u64 {
77        february.update_u64(
78            user,
79            &Event {
80                revenue_cents: 400,
81                country: "US",
82            },
83        );
84    }
85
86    println!("January unique users:  {:.0}", january.get_estimate());
87    println!("February unique users: {:.0}", february.get_estimate());
88
89    // Union: everyone who appeared in either month, with their activity merged.
90    let mut union = TupleUnionBuilder::<Activity>::new()
91        .lg_k(12)
92        .build()
93        .unwrap();
94    union.update(&january);
95    union.update(&february);
96    let combined = union.get_result(true);
97    println!("Users across both months: {:.0}", combined.get_estimate());
98
99    // Per-entry summaries are the point of a Tuple sketch. Scale the retained
100    // sample back up by 1/theta to estimate population totals.
101    let retained_revenue: u64 = combined.entries().map(|(_, a)| a.revenue_cents).sum();
102    let biggest_order = combined
103        .entries()
104        .map(|(_, a)| a.largest_order_cents)
105        .max()
106        .unwrap_or(0);
107    println!(
108        "Estimated total revenue: {:.2} (from {} retained entries, theta = {:.4})",
109        (retained_revenue as f64 / combined.get_theta()) / 100.0,
110        combined.get_num_retained(),
111        combined.get_theta()
112    );
113    println!(
114        "Largest single order seen: {:.2}",
115        biggest_order as f64 / 100.0
116    );
117
118    // Intersection: users active in both months.
119    let mut intersection = TupleIntersection::<Activity>::new();
120    intersection.update(&january);
121    intersection.update(&february);
122    match intersection.get_result(true) {
123        Ok(returning) => {
124            println!("Returning users: {:.0}", returning.get_estimate());
125            // `intersection_combine`'s `min` semantics at work: a returning
126            // user's sessions/countries reflect only what showed up in BOTH
127            // months, not the union of the two.
128            if let Some((_, activity)) = returning.entries().next() {
129                println!(
130                    "  e.g. one returning user: {} session(s), countries seen in both months: {:?}",
131                    activity.sessions, activity.countries
132                );
133            }
134        }
135        Err(e) => println!("No intersection result: {e}"),
136    }
137
138    // A-not-b: users who churned after January.
139    let churned = TupleAnotB::<Activity>::new().compute(&january, &february, true);
140    println!("Churned after January: {:.0}", churned.get_estimate());
141
142    // Jaccard similarity of the two months' audiences.
143    let similarity = tuple_jaccard_similarity(&january, &february);
144    println!(
145        "Audience overlap (Jaccard): {:.3} (range [{:.3}, {:.3}])",
146        similarity.estimate, similarity.lower_bound, similarity.upper_bound
147    );
148}
Source

pub fn lg_k(self, lg_k: u8) -> Self

Sets the base-2 log of the target number of retained entries.

Examples found in repository?
examples/tuple_generic.rs (line 91)
63fn main() {
64    let mut january: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
65    for user in 0..10_000u64 {
66        january.update_u64(
67            user,
68            &Event {
69                revenue_cents: 250 + (user % 100),
70                country: if user % 2 == 0 { "GB" } else { "US" },
71            },
72        );
73    }
74
75    let mut february: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
76    for user in 5_000..15_000u64 {
77        february.update_u64(
78            user,
79            &Event {
80                revenue_cents: 400,
81                country: "US",
82            },
83        );
84    }
85
86    println!("January unique users:  {:.0}", january.get_estimate());
87    println!("February unique users: {:.0}", february.get_estimate());
88
89    // Union: everyone who appeared in either month, with their activity merged.
90    let mut union = TupleUnionBuilder::<Activity>::new()
91        .lg_k(12)
92        .build()
93        .unwrap();
94    union.update(&january);
95    union.update(&february);
96    let combined = union.get_result(true);
97    println!("Users across both months: {:.0}", combined.get_estimate());
98
99    // Per-entry summaries are the point of a Tuple sketch. Scale the retained
100    // sample back up by 1/theta to estimate population totals.
101    let retained_revenue: u64 = combined.entries().map(|(_, a)| a.revenue_cents).sum();
102    let biggest_order = combined
103        .entries()
104        .map(|(_, a)| a.largest_order_cents)
105        .max()
106        .unwrap_or(0);
107    println!(
108        "Estimated total revenue: {:.2} (from {} retained entries, theta = {:.4})",
109        (retained_revenue as f64 / combined.get_theta()) / 100.0,
110        combined.get_num_retained(),
111        combined.get_theta()
112    );
113    println!(
114        "Largest single order seen: {:.2}",
115        biggest_order as f64 / 100.0
116    );
117
118    // Intersection: users active in both months.
119    let mut intersection = TupleIntersection::<Activity>::new();
120    intersection.update(&january);
121    intersection.update(&february);
122    match intersection.get_result(true) {
123        Ok(returning) => {
124            println!("Returning users: {:.0}", returning.get_estimate());
125            // `intersection_combine`'s `min` semantics at work: a returning
126            // user's sessions/countries reflect only what showed up in BOTH
127            // months, not the union of the two.
128            if let Some((_, activity)) = returning.entries().next() {
129                println!(
130                    "  e.g. one returning user: {} session(s), countries seen in both months: {:?}",
131                    activity.sessions, activity.countries
132                );
133            }
134        }
135        Err(e) => println!("No intersection result: {e}"),
136    }
137
138    // A-not-b: users who churned after January.
139    let churned = TupleAnotB::<Activity>::new().compute(&january, &february, true);
140    println!("Churned after January: {:.0}", churned.get_estimate());
141
142    // Jaccard similarity of the two months' audiences.
143    let similarity = tuple_jaccard_similarity(&january, &february);
144    println!(
145        "Audience overlap (Jaccard): {:.3} (range [{:.3}, {:.3}])",
146        similarity.estimate, similarity.lower_bound, similarity.upper_bound
147    );
148}
Source

pub fn resize_factor(self, resize_factor: ResizeFactor) -> Self

Sets the hash table’s growth ResizeFactor.

Source

pub fn p(self, p: f32) -> Self

Sets the sampling probability.

Source

pub fn build(self) -> Result<TupleUnion<S>, SketchError>

Builds the union. Returns SketchError::InvalidConfig if lg_k is out of range or p is outside (0, 1].

Examples found in repository?
examples/tuple_generic.rs (line 92)
63fn main() {
64    let mut january: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
65    for user in 0..10_000u64 {
66        january.update_u64(
67            user,
68            &Event {
69                revenue_cents: 250 + (user % 100),
70                country: if user % 2 == 0 { "GB" } else { "US" },
71            },
72        );
73    }
74
75    let mut february: TupleSketch<Activity> = TupleSketchBuilder::new().lg_k(12).build().unwrap();
76    for user in 5_000..15_000u64 {
77        february.update_u64(
78            user,
79            &Event {
80                revenue_cents: 400,
81                country: "US",
82            },
83        );
84    }
85
86    println!("January unique users:  {:.0}", january.get_estimate());
87    println!("February unique users: {:.0}", february.get_estimate());
88
89    // Union: everyone who appeared in either month, with their activity merged.
90    let mut union = TupleUnionBuilder::<Activity>::new()
91        .lg_k(12)
92        .build()
93        .unwrap();
94    union.update(&january);
95    union.update(&february);
96    let combined = union.get_result(true);
97    println!("Users across both months: {:.0}", combined.get_estimate());
98
99    // Per-entry summaries are the point of a Tuple sketch. Scale the retained
100    // sample back up by 1/theta to estimate population totals.
101    let retained_revenue: u64 = combined.entries().map(|(_, a)| a.revenue_cents).sum();
102    let biggest_order = combined
103        .entries()
104        .map(|(_, a)| a.largest_order_cents)
105        .max()
106        .unwrap_or(0);
107    println!(
108        "Estimated total revenue: {:.2} (from {} retained entries, theta = {:.4})",
109        (retained_revenue as f64 / combined.get_theta()) / 100.0,
110        combined.get_num_retained(),
111        combined.get_theta()
112    );
113    println!(
114        "Largest single order seen: {:.2}",
115        biggest_order as f64 / 100.0
116    );
117
118    // Intersection: users active in both months.
119    let mut intersection = TupleIntersection::<Activity>::new();
120    intersection.update(&january);
121    intersection.update(&february);
122    match intersection.get_result(true) {
123        Ok(returning) => {
124            println!("Returning users: {:.0}", returning.get_estimate());
125            // `intersection_combine`'s `min` semantics at work: a returning
126            // user's sessions/countries reflect only what showed up in BOTH
127            // months, not the union of the two.
128            if let Some((_, activity)) = returning.entries().next() {
129                println!(
130                    "  e.g. one returning user: {} session(s), countries seen in both months: {:?}",
131                    activity.sessions, activity.countries
132                );
133            }
134        }
135        Err(e) => println!("No intersection result: {e}"),
136    }
137
138    // A-not-b: users who churned after January.
139    let churned = TupleAnotB::<Activity>::new().compute(&january, &february, true);
140    println!("Churned after January: {:.0}", churned.get_estimate());
141
142    // Jaccard similarity of the two months' audiences.
143    let similarity = tuple_jaccard_similarity(&january, &february);
144    println!(
145        "Audience overlap (Jaccard): {:.3} (range [{:.3}, {:.3}])",
146        similarity.estimate, similarity.lower_bound, similarity.upper_bound
147    );
148}

Trait Implementations§

Source§

impl<S: TupleSummary> Clone for TupleUnionBuilder<S>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<S: TupleSummary> Copy for TupleUnionBuilder<S>

Source§

impl<S: TupleSummary> Debug for TupleUnionBuilder<S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<S: TupleSummary> Default for TupleUnionBuilder<S>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.