Module statkit.types

Classes

class Estimate (point: float, lower: float, upper: float)
Expand source code
class Estimate:
    """Estimate with range of uncertainty (95% confidence interval).

    Example:
        ```python
        mean = 1.0
        standard_deviation = 0.2
        estimate = Estimate(
            point=mean,
            lower=mean - 1.96*standard_deviation,
            upper=mean + 1.96*standard_deviation,
            )
        # Print estimate in LaTeX format.
        print(estimate.latex())
        ```
    """

    def __init__(self, point: float, lower: float, upper: float):
        """
        Args:
            point: Point estimate.
            lower: Lower limit of 95% confidence interval (CI).
            upper: Upper limit of 95% CI.
        """
        self.point = point
        self.lower = lower
        self.upper = upper

    def _significant_digits(self) -> int:
        """Number of significant digits"""
        upper_error = self.upper - self.point
        lower_error = self.point - self.lower
        error = max(upper_error, lower_error)
        return _get_number_of_significant_digits(self.point, error)

    def latex(self) -> str:
        """Format 95% confidence interval as LaTeX."""
        if any(np.isnan([self.point, self.lower, self.upper])):
            return r"\verb|<nan>|"

        n_digits = self._significant_digits()
        number, exponent = _parse_scientific_notation(self.point)

        if exponent == 0:
            fargs = (number, (self.upper - self.point), (self.lower - self.point))
            return (
                "{:."
                + str(n_digits - 1)
                + "f}$^{{+{:."
                + str(n_digits - 1)
                + "f}}}_{{{:."
                + str(n_digits - 1)
                + "f}}}$"
            ).format(*fargs)

        elif exponent == -1:
            fargs = (self.point, (self.upper - self.point), (self.lower - self.point))
            return (
                "{:."
                + str(n_digits)
                + "f}$^{{+{:."
                + str(n_digits)
                + "f}}}_{{{:."
                + str(n_digits)
                + "f}}}$"
            ).format(*fargs)

        fargs_with_exp = (
            number,
            (self.upper - self.point) / 10**exponent,
            (self.lower - self.point) / 10**exponent,
            exponent,
        )

        return (
            "{:."
            + str(n_digits - 1)
            + r"f}$^{{+{:."
            + str(n_digits - 1)
            + r"f}}}_{{{:."
            + str(n_digits - 1)
            + r"f}}} \cdot 10^{{{:}}}$"
        ).format(*fargs_with_exp)

    def __str__(self) -> str:
        """String representation of estimate with 95% confidence interval."""
        if any(np.isnan([self.point, self.lower, self.upper])):
            return "<nan>"

        n_digits = self._significant_digits()
        point_str = _format_float(self.point, n_digits)
        lower_str = _format_float(self.lower, n_digits)
        upper_str = _format_float(self.upper, n_digits)
        return f"{point_str} (95% CI: {lower_str}–{upper_str})"

    def __eq__(self, other) -> bool:
        """Estimates are equal if all their values are equal."""
        # Perhaps we should make a more lenient definition, that estimate is not
        # significantly different?
        return (
            (self.point == other.point)
            and (self.upper == other.upper)
            and (self.lower == other.lower)
        )

    def __repr__(self) -> str:
        """Machine friendly representation."""
        return f"Estimate({self.point}, lower={self.lower}, upper={self.upper})"

    def __iter__(self):
        """Make function representable as a dict."""
        yield "point", self.point
        yield "lower", self.lower
        yield "upper", self.upper

Estimate with range of uncertainty (95% confidence interval).

Example

mean = 1.0
standard_deviation = 0.2
estimate = Estimate(
    point=mean,
    lower=mean - 1.96*standard_deviation,
    upper=mean + 1.96*standard_deviation,
    )
# Print estimate in LaTeX format.
print(estimate.latex())

Args

point
Point estimate.
lower
Lower limit of 95% confidence interval (CI).
upper
Upper limit of 95% CI.

Methods

def latex(self) ‑> str
Expand source code
def latex(self) -> str:
    """Format 95% confidence interval as LaTeX."""
    if any(np.isnan([self.point, self.lower, self.upper])):
        return r"\verb|<nan>|"

    n_digits = self._significant_digits()
    number, exponent = _parse_scientific_notation(self.point)

    if exponent == 0:
        fargs = (number, (self.upper - self.point), (self.lower - self.point))
        return (
            "{:."
            + str(n_digits - 1)
            + "f}$^{{+{:."
            + str(n_digits - 1)
            + "f}}}_{{{:."
            + str(n_digits - 1)
            + "f}}}$"
        ).format(*fargs)

    elif exponent == -1:
        fargs = (self.point, (self.upper - self.point), (self.lower - self.point))
        return (
            "{:."
            + str(n_digits)
            + "f}$^{{+{:."
            + str(n_digits)
            + "f}}}_{{{:."
            + str(n_digits)
            + "f}}}$"
        ).format(*fargs)

    fargs_with_exp = (
        number,
        (self.upper - self.point) / 10**exponent,
        (self.lower - self.point) / 10**exponent,
        exponent,
    )

    return (
        "{:."
        + str(n_digits - 1)
        + r"f}$^{{+{:."
        + str(n_digits - 1)
        + r"f}}}_{{{:."
        + str(n_digits - 1)
        + r"f}}} \cdot 10^{{{:}}}$"
    ).format(*fargs_with_exp)

Format 95% confidence interval as LaTeX.