{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"\nThis module provides alternatives for the few additional functions found in\nand once used from the bottlechest package (fork of bottleneck).\n\nIt also patches bottleneck to contain these functions.\n\"\"\"\nimport warnings\nfrom typing import Iterable\n\nimport bottleneck as bn\nimport numpy as np\nimport scipy.stats.stats\nfrom scipy import sparse as sp\n\nfrom sklearn.utils.sparsefuncs import mean_variance_axis\n\nfrom Orange.data.util import array_equal\nfrom Orange.util import deprecated\n\n# For backwards compatibility\narray_equal = deprecated(\"Orange.data.util.array_equal\")(array_equal)\n\n\ndef _count_nans_per_row_sparse(X, weights, dtype=None):\n    \"\"\" Count the number of nans (undefined) values per row. \"\"\"\n    if weights is not None:\n        X = X.tocoo(copy=False)\n        nonzero_mask = np.isnan(X.data)\n        nan_rows, nan_cols = X.row[nonzero_mask], X.col[nonzero_mask]\n\n        if weights.ndim == 1:\n            data_weights = weights[nan_rows]\n        else:\n            data_weights = weights[nan_rows, nan_cols]\n\n        w = sp.coo_matrix((data_weights, (nan_rows, nan_cols)), shape=X.shape)\n        w = w.tocsr()\n        return np.asarray(w.sum(axis=1), dtype=dtype).ravel()\n\n    if isinstance(X, (sp.csr_matrix, sp.csc_matrix)):\n        X = type(X)((np.isnan(X.data), X.indices, X.indptr), X.shape)\n        return np.asarray(X.sum(axis=1), dtype=dtype).ravel()\n    else:  # pragma: no cover\n        raise TypeError(\"unsupported type '{}'\".format(type(X).__name__))\n\n\ndef sparse_count_implicit_zeros(x):\n    \"\"\" Count the number of implicit zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) - x.nnz\n\n\ndef sparse_has_implicit_zeros(x):\n    \"\"\" Check if sparse matrix contains any implicit zeros. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) != x.nnz\n\n\ndef sparse_implicit_zero_weights(x, weights):\n    \"\"\" Extract the weight values of all zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n\n    if weights.ndim == 1:\n        # Match weights and x axis so `indices` will be set appropriately\n        if x.shape[0] == weights.shape[0]:\n            x = x.tocsc()\n        elif x.shape[1] == weights.shape[0]:\n            x = x.tocsr()\n        n_items = np.prod(x.shape)\n        zero_indices = np.setdiff1d(np.arange(n_items), x.indices, assume_unique=True)\n        return weights[zero_indices]\n    else:\n        # Can easily be implemented using a coo_matrix\n        raise NotImplementedError(\n            'Computing zero weights on ndimensinal weight matrix is not implemented'\n        )\n\n\ndef bincount(x, weights=None, max_val=None, minlength=0):\n    \"\"\"Return counts of values in array X.\n\n    Works kind of like np.bincount(), except that it also supports floating\n    arrays with nans.\n\n    Parameters\n    ----------\n    x : array_like, 1 dimension, nonnegative ints\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same shape as x.\n    max_val : int, optional\n        Indicates the maximum value we expect to find in X and sets the result\n        array size accordingly. E.g. if we set `max_val=2` yet the largest\n        value in X is 1, the result will contain a bin for the value 2, and\n        will be set to 0. See examples for usage.\n    minlength : int, optional\n        A minimum number of bins for the output array. See numpy docs for info.\n\n    Returns\n    -------\n    Tuple[np.ndarray, int]\n        Returns the bincounts and the number of NaN values.\n\n    Examples\n    --------\n    In case `max_val` is provided, the return shape includes bins for these\n    values as well, even if they do not appear in the data. However, this will\n    not truncate the bincount if values larger than `max_count` are found.\n    >>> bincount([0, 0, 1, 1, 2], max_val=4)\n    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n    >>> bincount([0, 1, 2, 3, 4], max_val=2)\n    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n\n    \"\"\"\n    # Store the original matrix before any manipulation to check for sparse\n    x_original = x\n    if sp.issparse(x):\n        if weights is not None:\n            # Match weights and x axis so `indices` will be set appropriately\n            if x.shape[0] == weights.shape[0]:\n                x = x.tocsc()\n            elif x.shape[1] == weights.shape[0]:\n                x = x.tocsr()\n\n            zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n            weights = weights[x.indices]\n        else:\n            zero_weights = sparse_count_implicit_zeros(x)\n\n        x = x.data\n\n    x = np.asanyarray(x)\n    if x.dtype.kind == 'f' and bn.anynan(x):\n        nonnan = ~np.isnan(x)\n        x = x[nonnan]\n        if weights is not None:\n            nans = (~nonnan * weights).sum(axis=0)\n            weights = weights[nonnan]\n        else:\n            nans = (~nonnan).sum(axis=0)\n    else:\n        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n\n    if minlength == 0 and max_val is not None:\n        minlength = max_val + 1\n\n    bc = np.bincount(\n        x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n    ).astype(float)\n    # Since `csr_matrix.values` only contain non-zero values or explicit\n    # zeros, we must count implicit zeros separately and add them to the\n    # explicit ones found before\n    if sp.issparse(x_original):\n        # If x contains only NaNs, then bc will be an empty array\n        if zero_weights and bc.size == 0:\n            bc = [zero_weights]\n        elif zero_weights:\n            bc[0] += zero_weights\n\n    return bc, nans\n\n\ndef countnans(x, weights=None, axis=None, dtype=None, keepdims=False):\n    \"\"\"\n    Count the undefined elements in an array along given axis.\n\n    Parameters\n    ----------\n    x : array_like\n    weights : array_like, optional\n        Weights to weight the nans with, before or after counting (depending\n        on the weights shape).\n    axis : int, optional\n    dtype : dtype, optional\n        The data type of the returned array.\n\n    Returns\n    -------\n    Union[np.ndarray, float]\n\n    \"\"\"\n    if not sp.issparse(x):\n        x = np.asanyarray(x)\n        isnan = np.isnan(x)\n        if weights is not None and weights.shape == x.shape:\n            isnan = isnan * weights\n\n        counts = isnan.sum(axis=axis, dtype=dtype, keepdims=keepdims)\n        if weights is not None and weights.shape != x.shape:\n            counts = counts * weights\n    else:\n        assert axis in [None, 0, 1], 'Only axis 0 and 1 are currently supported'\n        # To have consistent behaviour with dense matrices, raise error when\n        # `axis=1` and the array is 1d (e.g. [[1 2 3]])\n        if x.shape[0] == 1 and axis == 1:\n            raise ValueError('Axis %d is out of bounds' % axis)\n\n        arr = x if axis == 1 else x.T\n\n        if weights is not None:\n            weights = weights if axis == 1 else weights.T\n\n        arr = arr.tocsr()\n        counts = _count_nans_per_row_sparse(arr, weights, dtype=dtype)\n\n        # We want a scalar value if `axis=None` or if the sparse matrix is\n        # actually a vector (e.g. [[1 2 3]]), but has `ndim=2` due to scipy\n        # implementation\n        if axis is None or x.shape[0] == 1:\n            counts = counts.sum(dtype=dtype)\n\n    return counts\n\n\ndef contingency(X, y, max_X=None, max_y=None, weights=None, mask=None):\n    \"\"\"\n    Compute the contingency matrices for each column of X (excluding the masked)\n    versus the vector y.\n\n    If the array is 1-dimensional, a 2d contingency matrix is returned. If the\n    array is 2d, the function returns a 3d array, with the first dimension\n    corresponding to column index (variable in the input array).\n\n    The rows of contingency matrix correspond to values of variables, the\n    columns correspond to values in vector `y`.\n    (??? isn't it the other way around ???)\n\n    Rows in the input array can be weighted (argument `weights`). A subset of\n    columns can be selected by additional argument `mask`.\n\n    The function also returns a count of NaN values per each value of `y`.\n\n    Parameters\n    ----------\n    X : array_like\n        With values in columns.\n    y : 1d array\n        Vector of true values.\n    max_X : int\n        The maximal value in the array\n    max_y : int\n        The maximal value in `y`\n    weights : array_like\n        Row weights. When not None, contingencies contain weighted counts\n    mask : sequence\n        Discrete columns of X.\n\n    Returns\n    -------\n    contingencies: (m × ny × nx) array\n        m number of masked (used) columns (all if mask=None), i.e.\n        for each column of X;\n        ny number of uniques in y,\n        nx number of uniques in column of X.\n    nans : array_like\n        Number of nans in each column of X for each unique value of y.\n    \"\"\"\n    was_1d = False\n    if X.ndim == 1:\n        X = X[..., np.newaxis]\n        was_1d = True\n\n    contingencies, nans = [], []\n    ny = np.unique(y).size if max_y is None else max_y + 1\n    for i in range(X.shape[1]):\n        if mask is not None and not mask[i]:\n            contingencies.append(np.zeros((ny, max_X + 1)))\n            nans.append(np.zeros(ny))\n            continue\n        col = X[..., i]\n        nx = np.unique(col[~np.isnan(col)]).size if max_X is None else max_X + 1\n        if sp.issparse(col):\n            col = np.ravel(col.todense())\n        contingencies.append(\n            bincount(y + ny * col,\n                     minlength=ny * nx,\n                     weights=weights)[0].reshape(nx, ny).T)\n        nans.append(\n            bincount(y[np.isnan(col)], minlength=ny)[0])\n    if was_1d:\n        return contingencies[0], nans[0]\n    return np.array(contingencies), np.array(nans)\n\n\ndef stats(X, weights=None, compute_variance=False):\n    \"\"\"\n    Compute min, max, #nans, mean and variance.\n\n    Result is a tuple (min, max, mean, variance, #nans, #non-nans) or an\n    array of shape (len(X), 6).\n\n    The mean and the number of nans and non-nans are weighted.\n\n    Computation of variance requires an additional pass and is not enabled\n    by default. Zeros are filled in instead of variance.\n\n    Parameters\n    ----------\n    X : array_like, 1 or 2 dimensions\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same length as `x`.\n    compute_variance : bool, optional\n        If set to True, the function also computes variance.\n\n    Returns\n    -------\n    out : a 6-element tuple or an array of shape (len(x), 6)\n        Computed (min, max, mean, variance or 0, #nans, #non-nans)\n\n    Raises\n    ------\n    ValueError\n        If the length of the weight vector does not match the length of the\n        array\n    \"\"\"\n    is_numeric = np.issubdtype(X.dtype, np.number)\n    is_sparse = sp.issparse(X)\n    weighted = weights is not None and X.dtype != object\n\n    def weighted_mean():\n        if is_sparse:\n            w_X = X.multiply(sp.csr_matrix(np.c_[weights] / sum(weights)))\n            return np.asarray(w_X.sum(axis=0)).ravel()\n        else:\n            return np.nansum(X * np.c_[weights] / sum(weights), axis=0)\n\n    if X.size and is_numeric and not is_sparse:\n        nans = np.isnan(X).sum(axis=0)\n        return np.column_stack((\n            np.nanmin(X, axis=0),\n            np.nanmax(X, axis=0),\n            np.nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.nanvar(X, axis=0) if compute_variance else np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n    elif is_sparse and X.size:\n        if compute_variance:\n            raise NotImplementedError\n\n        non_zero = np.bincount(X.nonzero()[1], minlength=X.shape[1])\n        X = X.tocsc()\n        return np.column_stack((\n            nanmin(X, axis=0),\n            nanmax(X, axis=0),\n            nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.zeros(X.shape[1]),      # variance not supported\n            X.shape[0] - non_zero,\n            non_zero))\n    else:\n        X_str = X.astype(str)\n        nans = ((X_str == \"nan\") | (X_str == \"\")).sum(axis=0) \\\n            if X.size else np.zeros(X.shape[1])\n        return np.column_stack((\n            np.tile(np.inf, X.shape[1]),\n            np.tile(-np.inf, X.shape[1]),\n            np.zeros(X.shape[1]),\n            np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n\n\ndef _nan_min_max(x, func, axis=0):\n    if not sp.issparse(x):\n        return func(x, axis=axis)\n    if axis is None:\n        extreme = func(x.data, axis=axis) if x.nnz else float('nan')\n        if sparse_has_implicit_zeros(x):\n            extreme = func([0, extreme])\n        return extreme\n    if axis == 0:\n        x = x.T\n    else:\n        assert axis == 1\n\n    # TODO check & transform to correct format\n    r = []\n    for row in x:\n        values = row.data\n        extreme = func(values) if values.size else float('nan')\n        if sparse_has_implicit_zeros(row):\n            extreme = func([0, extreme])\n        r.append(extreme)\n    return np.array(r)\n\n\ndef nanmin(x, axis=None):\n    \"\"\" Equivalent of np.nammin that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmin, axis)\n\n\ndef nanmax(x, axis=None):\n    \"\"\" Equivalent of np.nammax that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmax, axis)\n\n\ndef mean(x):\n    \"\"\" Equivalent of np.mean that supports sparse or dense matrices. \"\"\"\n    m = (np.sum(x.data) / np.prod(x.shape)\n         if sp.issparse(x) else\n         np.mean(x))\n    if np.isnan(m):\n        warnings.warn('mean() resulted in nan. If input can contain nan values,'\n                      ' perhaps you meant nanmean?', stacklevel=2)\n    return m\n\n\ndef _apply_func(x, dense_func, sparse_func, axis=None):\n    \"\"\" General wrapper for a function depending on sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return dense_func(x, axis=axis)\n    if axis is None:\n        return sparse_func(x)\n    if axis in [0, 1]:\n        arr = x if axis == 1 else x.T\n        arr = arr.tocsr()\n        return np.fromiter((sparse_func(row) for row in arr),\n                           dtype=np.double, count=arr.shape[0])\n    else:\n        raise NotImplementedError\n\n\ndef nansum(x, axis=None):\n    \"\"\" Equivalent of np.nansum that supports sparse or dense matrices. \"\"\"\n    def nansum_sparse(x):\n        return np.nansum(x.data)\n\n    return _apply_func(x, np.nansum, nansum_sparse, axis=axis)\n\n\ndef nanmean(x, axis=None):\n    \"\"\" Equivalent of np.nanmean that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        means = np.nanmean(x, axis=axis)\n    elif axis is None:\n        means, _ = mean_variance_axis(x, axis=0)\n        means = np.nanmean(means)\n    else:\n        means, _ = mean_variance_axis(x, axis=axis)\n\n    return means\n\n\ndef nanvar(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanvar that supports sparse or dense matrices. \"\"\"\n    def nanvar_sparse(x):\n        n_vals = np.prod(x.shape) - np.sum(np.isnan(x.data))\n        n_zeros = np.prod(x.shape) - len(x.data)\n        mean = np.nansum(x.data) / n_vals\n        return (np.nansum((x.data - mean) ** 2) + mean ** 2 * n_zeros) / (n_vals - ddof)\n\n    return _apply_func(x, np.nanvar, nanvar_sparse, axis=axis)\n\n\ndef nanstd(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanstd that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(nanvar(x, axis=axis, ddof=ddof))\n\n\ndef nanmedian(x, axis=None):\n    \"\"\" Equivalent of np.nanmedian that supports sparse or dense matrices. \"\"\"\n    def nanmedian_sparse(x):\n        nz = np.logical_not(np.isnan(x.data))\n        n_nan = sum(np.isnan(x.data))\n        n_nonzero = sum(x.data[nz] != 0)\n        n_zeros = np.prod(x.shape) - n_nonzero - n_nan\n        if n_zeros > n_nonzero:\n            # Typical case if use of sparse matrices make sense\n            return 0\n        else:\n            # Possibly contains NaNs and\n            # more nz values than zeros, so allocating memory should not be too problematic\n            return np.nanmedian(x.toarray())\n\n    return _apply_func(x, np.nanmedian, nanmedian_sparse, axis=axis)\n\n\ndef nanmode(x, axis=0):\n    \"\"\" A temporary replacement for a scipy.stats.mode.\n\n    This function returns mode NaN if all values are NaN (scipy<1.2.0 wrongly\n    returns zero). Also, this function returns count NaN if all values are NaN\n    (scipy=1.3.0 returns some number).\"\"\"\n    nans = np.isnan(np.array(x)).sum(axis=axis, keepdims=True) == x.shape[axis]\n    res = scipy.stats.stats.mode(x, axis)\n    return scipy.stats.stats.ModeResult(np.where(nans, np.nan, res.mode),\n                                        np.where(nans, np.nan, res.count))\n\n\ndef unique(x, return_counts=False):\n    \"\"\" Equivalent of np.unique that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.unique(x, return_counts=return_counts)\n\n    implicit_zeros = sparse_count_implicit_zeros(x)\n    explicit_zeros = not np.all(x.data)\n    r = np.unique(x.data, return_counts=return_counts)\n    if not implicit_zeros:\n        return r\n\n    if return_counts:\n        zero_index = np.searchsorted(r[0], 0)\n        if explicit_zeros:\n            r[1][r[0] == 0.] += implicit_zeros\n            return r\n        return np.insert(r[0], zero_index, 0), np.insert(r[1], zero_index, implicit_zeros)\n    else:\n        if explicit_zeros:\n            return r\n        zero_index = np.searchsorted(r, 0)\n        return np.insert(r, zero_index, 0)\n\n\ndef nanunique(*args, **kwargs):\n    \"\"\" Return unique values while disregarding missing (np.nan) values.\n    Supports sparse or dense matrices. \"\"\"\n    result = unique(*args, **kwargs)\n\n    if isinstance(result, tuple):\n        result, counts = result\n        non_nan_mask = ~np.isnan(result)\n        return result[non_nan_mask], counts[non_nan_mask]\n\n    return result[~np.isnan(result)]\n\n\ndef digitize(x, bins, right=False):\n    \"\"\"Equivalent of np.digitize that supports sparse and dense matrices.\n\n    If a sparse matrix is provided and the '0's belong to the '0'th bin, then\n    a sparse matrix is returned.\n\n    Because this can return both sparse and dense matrices, we must keep the\n    return shape consistent. Since sparse matrices don't support 1d matrices,\n    we reshape any returned 1d numpy array to a 2d matrix, with the first\n    dimension shape being 1. This is equivalent to the behaviour of sparse\n    matrices.\n\n    Parameters\n    ----------\n    x : Union[np.ndarry, sp.csr_matrix, sp.csc_matrix]\n    bins : np.ndarray\n    right : Optional[bool]\n\n    Returns\n    -------\n    Union[np.ndarray, sp.csr_matrix]\n\n    \"\"\"\n    if not sp.issparse(x):\n        # TODO Remove reshaping logic when support for numpy==1.9 is dropped\n        original_shape = x.shape\n        x = x.flatten()\n        result = np.digitize(x, bins, right)\n        result = result.reshape(original_shape)\n        # In order to keep the return shape consistent, and sparse matrices\n        # don't support 1d matrices, make sure to convert 1d to 2d matrices\n        if result.ndim == 1:\n            result = result.reshape(((1,) + result.shape))\n        return result\n\n    # Find the bin where zeros belong, depending on the `right` parameter\n    zero_bin = np.searchsorted(bins, 0, side=['right', 'left'][right])\n\n    if zero_bin == 0:\n        r = sp.lil_matrix(x.shape, dtype=np.int64)\n    else:\n        r = zero_bin * np.ones(x.shape, dtype=np.int64)\n\n    for idx, row in enumerate(x.tocsr()):\n        # TODO Remove this check when support for numpy==1.9 is dropped\n        if row.nnz > 0:\n            r[idx, row.indices] = np.digitize(row.data, bins, right)\n\n    # Orange mainly deals with `csr_matrix`, but `lil_matrix` is more efficient\n    # for incremental building\n    if sp.issparse(r):\n        r = r.tocsr()\n\n    return r\n\n\ndef var(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.var that supports sparse and dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.var(x, axis, ddof=ddof)\n\n    result = x.multiply(x).mean(axis) - np.square(x.mean(axis))\n    result = np.squeeze(np.asarray(result))\n\n    # Apply correction for degrees of freedom\n    n = np.prod(x.shape) if axis is None else x.shape[axis]\n    result *= n / (n - ddof)\n\n    return result\n\n\ndef std(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.std that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(var(x, axis=axis, ddof=ddof))\n\n\ndef FDR(p_values: Iterable, dependent=False, m=None, ordered=False) -> Iterable:\n    \"\"\" `False Discovery Rate <http://en.wikipedia.org/wiki/False_discovery_rate>`_\n        correction on a list of p-values.\n\n    :param p_values: list or np.ndarray of p-values.\n    :param dependent: use correction for dependent hypotheses (default False).\n    :param m: number of hypotheses tested (default ``len(p_values)``).\n    :param ordered: prevent sorting of p-values if they are already sorted\n        (default False).\n    :return: list or np.ndarray, same as the input\n    \"\"\"\n    if p_values is None or len(p_values) == 0 or \\\n            (m is not None and m <= 0):\n        return None\n\n    is_list = isinstance(p_values, list)\n    p_values = np.array(p_values)\n    if m is None:\n        m = len(p_values)\n    if not ordered:\n        ordered = (np.diff(p_values) >= 0).all()\n        if not ordered:\n            indices = np.argsort(p_values)\n            p_values = p_values[indices]\n\n    if dependent:  # correct q for dependent tests\n        m *= sum(1 / np.arange(1, m + 1))\n\n    fdrs = (p_values * m / np.arange(1, len(p_values) + 1))[::-1]\n    fdrs = np.array(np.minimum.accumulate(fdrs)[::-1])\n    if not ordered:\n        fdrs[indices] = fdrs.copy()\n    return fdrs if not is_list else list(fdrs)\n",
            "new_file_content": "\"\"\"\nThis module provides alternatives for the few additional functions found in\nand once used from the bottlechest package (fork of bottleneck).\n\nIt also patches bottleneck to contain these functions.\n\"\"\"\nimport warnings\nfrom typing import Iterable\n\nimport bottleneck as bn\nimport numpy as np\nimport scipy.stats.stats\nfrom scipy import sparse as sp\n\nfrom sklearn.utils.sparsefuncs import mean_variance_axis\n\nfrom Orange.data.util import array_equal\nfrom Orange.util import deprecated\n\n# For backwards compatibility\narray_equal = deprecated(\"Orange.data.util.array_equal\")(array_equal)\n\n\ndef _count_nans_per_row_sparse(X, weights, dtype=None):\n    \"\"\" Count the number of nans (undefined) values per row. \"\"\"\n    if weights is not None:\n        X = X.tocoo(copy=False)\n        nonzero_mask = np.isnan(X.data)\n        nan_rows, nan_cols = X.row[nonzero_mask], X.col[nonzero_mask]\n\n        if weights.ndim == 1:\n            data_weights = weights[nan_rows]\n        else:\n            data_weights = weights[nan_rows, nan_cols]\n\n        w = sp.coo_matrix((data_weights, (nan_rows, nan_cols)), shape=X.shape)\n        w = w.tocsr()\n        return np.asarray(w.sum(axis=1), dtype=dtype).ravel()\n\n    if isinstance(X, (sp.csr_matrix, sp.csc_matrix)):\n        X = type(X)((np.isnan(X.data), X.indices, X.indptr), X.shape)\n        return np.asarray(X.sum(axis=1), dtype=dtype).ravel()\n    else:  # pragma: no cover\n        raise TypeError(\"unsupported type '{}'\".format(type(X).__name__))\n\n\ndef sparse_count_implicit_zeros(x):\n    \"\"\" Count the number of implicit zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) - x.nnz\n\n\ndef sparse_has_implicit_zeros(x):\n    \"\"\" Check if sparse matrix contains any implicit zeros. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) != x.nnz\n\n\ndef sparse_implicit_zero_weights(x, weights):\n    \"\"\" Extract the weight values of all zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n\n    if weights.ndim == 1:\n        # Match weights and x axis so `indices` will be set appropriately\n        if x.shape[0] == weights.shape[0]:\n            x = x.tocsc()\n        elif x.shape[1] == weights.shape[0]:\n            x = x.tocsr()\n        n_items = np.prod(x.shape)\n        zero_indices = np.setdiff1d(np.arange(n_items), x.indices, assume_unique=True)\n        return weights[zero_indices]\n    else:\n        # Can easily be implemented using a coo_matrix\n        raise NotImplementedError(\n            'Computing zero weights on ndimensinal weight matrix is not implemented'\n        )\n\n\ndef bincount(x, weights=None, max_val=None, minlength=0):\n    \"\"\"Return counts of values in array X.\n\n    Works kind of like np.bincount(), except that it also supports\n    arrays with nans.\n\n    Parameters\n    ----------\n    x : array_like, 1 dimension, nonnegative ints\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same shape as x.\n    max_val : int, optional\n        Indicates the maximum value we expect to find in X and sets the result\n        array size accordingly. E.g. if we set `max_val=2` yet the largest\n        value in X is 1, the result will contain a bin for the value 2, and\n        will be set to 0. See examples for usage.\n    minlength : int, optional\n        A minimum number of bins for the output array. See numpy docs for info.\n\n    Returns\n    -------\n    Tuple[np.ndarray, int]\n        Returns the bincounts and the number of NaN values.\n\n    Examples\n    --------\n    In case `max_val` is provided, the return shape includes bins for these\n    values as well, even if they do not appear in the data. However, this will\n    not truncate the bincount if values larger than `max_count` are found.\n    >>> bincount([0, 0, 1, 1, 2], max_val=4)\n    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n    >>> bincount([0, 1, 2, 3, 4], max_val=2)\n    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n\n    \"\"\"\n    # Store the original matrix before any manipulation to check for sparse\n    x_original = x\n    if sp.issparse(x):\n        if weights is not None:\n            # Match weights and x axis so `indices` will be set appropriately\n            if x.shape[0] == weights.shape[0]:\n                x = x.tocsc()\n            elif x.shape[1] == weights.shape[0]:\n                x = x.tocsr()\n\n            zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n            weights = weights[x.indices]\n        else:\n            zero_weights = sparse_count_implicit_zeros(x)\n\n        x = x.data\n\n    x = np.asanyarray(x, dtype=float)\n    if bn.anynan(x):\n        nonnan = ~np.isnan(x)\n        x = x[nonnan]\n        if weights is not None:\n            nans = (~nonnan * weights).sum(axis=0)\n            weights = weights[nonnan]\n        else:\n            nans = (~nonnan).sum(axis=0)\n    else:\n        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n\n    if minlength == 0 and max_val is not None:\n        minlength = max_val + 1\n\n    bc = np.bincount(\n        x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n    ).astype(float)\n    # Since `csr_matrix.values` only contain non-zero values or explicit\n    # zeros, we must count implicit zeros separately and add them to the\n    # explicit ones found before\n    if sp.issparse(x_original):\n        # If x contains only NaNs, then bc will be an empty array\n        if zero_weights and bc.size == 0:\n            bc = [zero_weights]\n        elif zero_weights:\n            bc[0] += zero_weights\n\n    return bc, nans\n\n\ndef countnans(x, weights=None, axis=None, dtype=None, keepdims=False):\n    \"\"\"\n    Count the undefined elements in an array along given axis.\n\n    Parameters\n    ----------\n    x : array_like\n    weights : array_like, optional\n        Weights to weight the nans with, before or after counting (depending\n        on the weights shape).\n    axis : int, optional\n    dtype : dtype, optional\n        The data type of the returned array.\n\n    Returns\n    -------\n    Union[np.ndarray, float]\n\n    \"\"\"\n    if not sp.issparse(x):\n        x = np.asanyarray(x)\n        isnan = np.isnan(x)\n        if weights is not None and weights.shape == x.shape:\n            isnan = isnan * weights\n\n        counts = isnan.sum(axis=axis, dtype=dtype, keepdims=keepdims)\n        if weights is not None and weights.shape != x.shape:\n            counts = counts * weights\n    else:\n        assert axis in [None, 0, 1], 'Only axis 0 and 1 are currently supported'\n        # To have consistent behaviour with dense matrices, raise error when\n        # `axis=1` and the array is 1d (e.g. [[1 2 3]])\n        if x.shape[0] == 1 and axis == 1:\n            raise ValueError('Axis %d is out of bounds' % axis)\n\n        arr = x if axis == 1 else x.T\n\n        if weights is not None:\n            weights = weights if axis == 1 else weights.T\n\n        arr = arr.tocsr()\n        counts = _count_nans_per_row_sparse(arr, weights, dtype=dtype)\n\n        # We want a scalar value if `axis=None` or if the sparse matrix is\n        # actually a vector (e.g. [[1 2 3]]), but has `ndim=2` due to scipy\n        # implementation\n        if axis is None or x.shape[0] == 1:\n            counts = counts.sum(dtype=dtype)\n\n    return counts\n\n\ndef contingency(X, y, max_X=None, max_y=None, weights=None, mask=None):\n    \"\"\"\n    Compute the contingency matrices for each column of X (excluding the masked)\n    versus the vector y.\n\n    If the array is 1-dimensional, a 2d contingency matrix is returned. If the\n    array is 2d, the function returns a 3d array, with the first dimension\n    corresponding to column index (variable in the input array).\n\n    The rows of contingency matrix correspond to values of variables, the\n    columns correspond to values in vector `y`.\n    (??? isn't it the other way around ???)\n\n    Rows in the input array can be weighted (argument `weights`). A subset of\n    columns can be selected by additional argument `mask`.\n\n    The function also returns a count of NaN values per each value of `y`.\n\n    Parameters\n    ----------\n    X : array_like\n        With values in columns.\n    y : 1d array\n        Vector of true values.\n    max_X : int\n        The maximal value in the array\n    max_y : int\n        The maximal value in `y`\n    weights : array_like\n        Row weights. When not None, contingencies contain weighted counts\n    mask : sequence\n        Discrete columns of X.\n\n    Returns\n    -------\n    contingencies: (m × ny × nx) array\n        m number of masked (used) columns (all if mask=None), i.e.\n        for each column of X;\n        ny number of uniques in y,\n        nx number of uniques in column of X.\n    nans : array_like\n        Number of nans in each column of X for each unique value of y.\n    \"\"\"\n    was_1d = False\n    if X.ndim == 1:\n        X = X[..., np.newaxis]\n        was_1d = True\n\n    contingencies, nans = [], []\n    ny = np.unique(y).size if max_y is None else max_y + 1\n    for i in range(X.shape[1]):\n        if mask is not None and not mask[i]:\n            contingencies.append(np.zeros((ny, max_X + 1)))\n            nans.append(np.zeros(ny))\n            continue\n        col = X[..., i]\n        nx = np.unique(col[~np.isnan(col)]).size if max_X is None else max_X + 1\n        if sp.issparse(col):\n            col = np.ravel(col.todense())\n        contingencies.append(\n            bincount(y + ny * col,\n                     minlength=ny * nx,\n                     weights=weights)[0].reshape(nx, ny).T)\n        nans.append(\n            bincount(y[np.isnan(col)], minlength=ny)[0])\n    if was_1d:\n        return contingencies[0], nans[0]\n    return np.array(contingencies), np.array(nans)\n\n\ndef stats(X, weights=None, compute_variance=False):\n    \"\"\"\n    Compute min, max, #nans, mean and variance.\n\n    Result is a tuple (min, max, mean, variance, #nans, #non-nans) or an\n    array of shape (len(X), 6).\n\n    The mean and the number of nans and non-nans are weighted.\n\n    Computation of variance requires an additional pass and is not enabled\n    by default. Zeros are filled in instead of variance.\n\n    Parameters\n    ----------\n    X : array_like, 1 or 2 dimensions\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same length as `x`.\n    compute_variance : bool, optional\n        If set to True, the function also computes variance.\n\n    Returns\n    -------\n    out : a 6-element tuple or an array of shape (len(x), 6)\n        Computed (min, max, mean, variance or 0, #nans, #non-nans)\n\n    Raises\n    ------\n    ValueError\n        If the length of the weight vector does not match the length of the\n        array\n    \"\"\"\n    is_numeric = np.issubdtype(X.dtype, np.number)\n    is_sparse = sp.issparse(X)\n    weighted = weights is not None and X.dtype != object\n\n    def weighted_mean():\n        if is_sparse:\n            w_X = X.multiply(sp.csr_matrix(np.c_[weights] / sum(weights)))\n            return np.asarray(w_X.sum(axis=0)).ravel()\n        else:\n            return np.nansum(X * np.c_[weights] / sum(weights), axis=0)\n\n    if X.size and is_numeric and not is_sparse:\n        nans = np.isnan(X).sum(axis=0)\n        return np.column_stack((\n            np.nanmin(X, axis=0),\n            np.nanmax(X, axis=0),\n            np.nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.nanvar(X, axis=0) if compute_variance else np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n    elif is_sparse and X.size:\n        if compute_variance:\n            raise NotImplementedError\n\n        non_zero = np.bincount(X.nonzero()[1], minlength=X.shape[1])\n        X = X.tocsc()\n        return np.column_stack((\n            nanmin(X, axis=0),\n            nanmax(X, axis=0),\n            nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.zeros(X.shape[1]),      # variance not supported\n            X.shape[0] - non_zero,\n            non_zero))\n    else:\n        X_str = X.astype(str)\n        nans = ((X_str == \"nan\") | (X_str == \"\")).sum(axis=0) \\\n            if X.size else np.zeros(X.shape[1])\n        return np.column_stack((\n            np.tile(np.inf, X.shape[1]),\n            np.tile(-np.inf, X.shape[1]),\n            np.zeros(X.shape[1]),\n            np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n\n\ndef _nan_min_max(x, func, axis=0):\n    if not sp.issparse(x):\n        return func(x, axis=axis)\n    if axis is None:\n        extreme = func(x.data, axis=axis) if x.nnz else float('nan')\n        if sparse_has_implicit_zeros(x):\n            extreme = func([0, extreme])\n        return extreme\n    if axis == 0:\n        x = x.T\n    else:\n        assert axis == 1\n\n    # TODO check & transform to correct format\n    r = []\n    for row in x:\n        values = row.data\n        extreme = func(values) if values.size else float('nan')\n        if sparse_has_implicit_zeros(row):\n            extreme = func([0, extreme])\n        r.append(extreme)\n    return np.array(r)\n\n\ndef nanmin(x, axis=None):\n    \"\"\" Equivalent of np.nammin that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmin, axis)\n\n\ndef nanmax(x, axis=None):\n    \"\"\" Equivalent of np.nammax that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmax, axis)\n\n\ndef mean(x):\n    \"\"\" Equivalent of np.mean that supports sparse or dense matrices. \"\"\"\n    m = (np.sum(x.data) / np.prod(x.shape)\n         if sp.issparse(x) else\n         np.mean(x))\n    if np.isnan(m):\n        warnings.warn('mean() resulted in nan. If input can contain nan values,'\n                      ' perhaps you meant nanmean?', stacklevel=2)\n    return m\n\n\ndef _apply_func(x, dense_func, sparse_func, axis=None):\n    \"\"\" General wrapper for a function depending on sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return dense_func(x, axis=axis)\n    if axis is None:\n        return sparse_func(x)\n    if axis in [0, 1]:\n        arr = x if axis == 1 else x.T\n        arr = arr.tocsr()\n        return np.fromiter((sparse_func(row) for row in arr),\n                           dtype=np.double, count=arr.shape[0])\n    else:\n        raise NotImplementedError\n\n\ndef nansum(x, axis=None):\n    \"\"\" Equivalent of np.nansum that supports sparse or dense matrices. \"\"\"\n    def nansum_sparse(x):\n        return np.nansum(x.data)\n\n    return _apply_func(x, np.nansum, nansum_sparse, axis=axis)\n\n\ndef nanmean(x, axis=None):\n    \"\"\" Equivalent of np.nanmean that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        means = np.nanmean(x, axis=axis)\n    elif axis is None:\n        means, _ = mean_variance_axis(x, axis=0)\n        means = np.nanmean(means)\n    else:\n        means, _ = mean_variance_axis(x, axis=axis)\n\n    return means\n\n\ndef nanvar(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanvar that supports sparse or dense matrices. \"\"\"\n    def nanvar_sparse(x):\n        n_vals = np.prod(x.shape) - np.sum(np.isnan(x.data))\n        n_zeros = np.prod(x.shape) - len(x.data)\n        mean = np.nansum(x.data) / n_vals\n        return (np.nansum((x.data - mean) ** 2) + mean ** 2 * n_zeros) / (n_vals - ddof)\n\n    return _apply_func(x, np.nanvar, nanvar_sparse, axis=axis)\n\n\ndef nanstd(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanstd that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(nanvar(x, axis=axis, ddof=ddof))\n\n\ndef nanmedian(x, axis=None):\n    \"\"\" Equivalent of np.nanmedian that supports sparse or dense matrices. \"\"\"\n    def nanmedian_sparse(x):\n        nz = np.logical_not(np.isnan(x.data))\n        n_nan = sum(np.isnan(x.data))\n        n_nonzero = sum(x.data[nz] != 0)\n        n_zeros = np.prod(x.shape) - n_nonzero - n_nan\n        if n_zeros > n_nonzero:\n            # Typical case if use of sparse matrices make sense\n            return 0\n        else:\n            # Possibly contains NaNs and\n            # more nz values than zeros, so allocating memory should not be too problematic\n            return np.nanmedian(x.toarray())\n\n    return _apply_func(x, np.nanmedian, nanmedian_sparse, axis=axis)\n\n\ndef nanmode(x, axis=0):\n    \"\"\" A temporary replacement for a scipy.stats.mode.\n\n    This function returns mode NaN if all values are NaN (scipy<1.2.0 wrongly\n    returns zero). Also, this function returns count NaN if all values are NaN\n    (scipy=1.3.0 returns some number).\"\"\"\n    nans = np.isnan(np.array(x)).sum(axis=axis, keepdims=True) == x.shape[axis]\n    res = scipy.stats.stats.mode(x, axis)\n    return scipy.stats.stats.ModeResult(np.where(nans, np.nan, res.mode),\n                                        np.where(nans, np.nan, res.count))\n\n\ndef unique(x, return_counts=False):\n    \"\"\" Equivalent of np.unique that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.unique(x, return_counts=return_counts)\n\n    implicit_zeros = sparse_count_implicit_zeros(x)\n    explicit_zeros = not np.all(x.data)\n    r = np.unique(x.data, return_counts=return_counts)\n    if not implicit_zeros:\n        return r\n\n    if return_counts:\n        zero_index = np.searchsorted(r[0], 0)\n        if explicit_zeros:\n            r[1][r[0] == 0.] += implicit_zeros\n            return r\n        return np.insert(r[0], zero_index, 0), np.insert(r[1], zero_index, implicit_zeros)\n    else:\n        if explicit_zeros:\n            return r\n        zero_index = np.searchsorted(r, 0)\n        return np.insert(r, zero_index, 0)\n\n\ndef nanunique(*args, **kwargs):\n    \"\"\" Return unique values while disregarding missing (np.nan) values.\n    Supports sparse or dense matrices. \"\"\"\n    result = unique(*args, **kwargs)\n\n    if isinstance(result, tuple):\n        result, counts = result\n        non_nan_mask = ~np.isnan(result)\n        return result[non_nan_mask], counts[non_nan_mask]\n\n    return result[~np.isnan(result)]\n\n\ndef digitize(x, bins, right=False):\n    \"\"\"Equivalent of np.digitize that supports sparse and dense matrices.\n\n    If a sparse matrix is provided and the '0's belong to the '0'th bin, then\n    a sparse matrix is returned.\n\n    Because this can return both sparse and dense matrices, we must keep the\n    return shape consistent. Since sparse matrices don't support 1d matrices,\n    we reshape any returned 1d numpy array to a 2d matrix, with the first\n    dimension shape being 1. This is equivalent to the behaviour of sparse\n    matrices.\n\n    Parameters\n    ----------\n    x : Union[np.ndarry, sp.csr_matrix, sp.csc_matrix]\n    bins : np.ndarray\n    right : Optional[bool]\n\n    Returns\n    -------\n    Union[np.ndarray, sp.csr_matrix]\n\n    \"\"\"\n    if not sp.issparse(x):\n        # TODO Remove reshaping logic when support for numpy==1.9 is dropped\n        original_shape = x.shape\n        x = x.flatten()\n        result = np.digitize(x, bins, right)\n        result = result.reshape(original_shape)\n        # In order to keep the return shape consistent, and sparse matrices\n        # don't support 1d matrices, make sure to convert 1d to 2d matrices\n        if result.ndim == 1:\n            result = result.reshape(((1,) + result.shape))\n        return result\n\n    # Find the bin where zeros belong, depending on the `right` parameter\n    zero_bin = np.searchsorted(bins, 0, side=['right', 'left'][right])\n\n    if zero_bin == 0:\n        r = sp.lil_matrix(x.shape, dtype=np.int64)\n    else:\n        r = zero_bin * np.ones(x.shape, dtype=np.int64)\n\n    for idx, row in enumerate(x.tocsr()):\n        # TODO Remove this check when support for numpy==1.9 is dropped\n        if row.nnz > 0:\n            r[idx, row.indices] = np.digitize(row.data, bins, right)\n\n    # Orange mainly deals with `csr_matrix`, but `lil_matrix` is more efficient\n    # for incremental building\n    if sp.issparse(r):\n        r = r.tocsr()\n\n    return r\n\n\ndef var(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.var that supports sparse and dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.var(x, axis, ddof=ddof)\n\n    result = x.multiply(x).mean(axis) - np.square(x.mean(axis))\n    result = np.squeeze(np.asarray(result))\n\n    # Apply correction for degrees of freedom\n    n = np.prod(x.shape) if axis is None else x.shape[axis]\n    result *= n / (n - ddof)\n\n    return result\n\n\ndef std(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.std that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(var(x, axis=axis, ddof=ddof))\n\n\ndef FDR(p_values: Iterable, dependent=False, m=None, ordered=False) -> Iterable:\n    \"\"\" `False Discovery Rate <http://en.wikipedia.org/wiki/False_discovery_rate>`_\n        correction on a list of p-values.\n\n    :param p_values: list or np.ndarray of p-values.\n    :param dependent: use correction for dependent hypotheses (default False).\n    :param m: number of hypotheses tested (default ``len(p_values)``).\n    :param ordered: prevent sorting of p-values if they are already sorted\n        (default False).\n    :return: list or np.ndarray, same as the input\n    \"\"\"\n    if p_values is None or len(p_values) == 0 or \\\n            (m is not None and m <= 0):\n        return None\n\n    is_list = isinstance(p_values, list)\n    p_values = np.array(p_values)\n    if m is None:\n        m = len(p_values)\n    if not ordered:\n        ordered = (np.diff(p_values) >= 0).all()\n        if not ordered:\n            indices = np.argsort(p_values)\n            p_values = p_values[indices]\n\n    if dependent:  # correct q for dependent tests\n        m *= sum(1 / np.arange(1, m + 1))\n\n    fdrs = (p_values * m / np.arange(1, len(p_values) + 1))[::-1]\n    fdrs = np.array(np.minimum.accumulate(fdrs)[::-1])\n    if not ordered:\n        fdrs[indices] = fdrs.copy()\n    return fdrs if not is_list else list(fdrs)\n",
            "header": {
                "file": {
                    "path": "Orange/statistics/util.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "a57156455",
                "new_commit_hash": "a4c2bcc32",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/statistics/util.py"
            },
            "plus_file": {
                "path": "b/Orange/statistics/util.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 82,
                            "length": 7
                        },
                        "new_range": {
                            "start": 82,
                            "length": 7
                        },
                        "section": "def sparse_implicit_zero_weights(x, weights):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "def bincount(x, weights=None, max_val=None, minlength=0):",
                                "type": "context"
                            },
                            {
                                "content": "    \"\"\"Return counts of values in array X.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    Works kind of like np.bincount(), except that it also supports floating",
                                "type": "deleted"
                            },
                            {
                                "content": "    Works kind of like np.bincount(), except that it also supports",
                                "type": "added"
                            },
                            {
                                "content": "    arrays with nans.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    Parameters",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/statistics/util.py",
                            "type": "function",
                            "name": "bincount",
                            "content": "def bincount(x, weights=None, max_val=None, minlength=0):\n    \"\"\"Return counts of values in array X.\n\n    Works kind of like np.bincount(), except that it also supports floating\n    arrays with nans.\n\n    Parameters\n    ----------\n    x : array_like, 1 dimension, nonnegative ints\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same shape as x.\n    max_val : int, optional\n        Indicates the maximum value we expect to find in X and sets the result\n        array size accordingly. E.g. if we set `max_val=2` yet the largest\n        value in X is 1, the result will contain a bin for the value 2, and\n        will be set to 0. See examples for usage.\n    minlength : int, optional\n        A minimum number of bins for the output array. See numpy docs for info.\n\n    Returns\n    -------\n    Tuple[np.ndarray, int]\n        Returns the bincounts and the number of NaN values.\n\n    Examples\n    --------\n    In case `max_val` is provided, the return shape includes bins for these\n    values as well, even if they do not appear in the data. However, this will\n    not truncate the bincount if values larger than `max_count` are found.\n    >>> bincount([0, 0, 1, 1, 2], max_val=4)\n    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n    >>> bincount([0, 1, 2, 3, 4], max_val=2)\n    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n\n    \"\"\"\n    # Store the original matrix before any manipulation to check for sparse\n    x_original = x\n    if sp.issparse(x):\n        if weights is not None:\n            # Match weights and x axis so `indices` will be set appropriately\n            if x.shape[0] == weights.shape[0]:\n                x = x.tocsc()\n            elif x.shape[1] == weights.shape[0]:\n                x = x.tocsr()\n\n            zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n            weights = weights[x.indices]\n        else:\n            zero_weights = sparse_count_implicit_zeros(x)\n\n        x = x.data\n\n    x = np.asanyarray(x)\n    if x.dtype.kind == 'f' and bn.anynan(x):\n        nonnan = ~np.isnan(x)\n        x = x[nonnan]\n        if weights is not None:\n            nans = (~nonnan * weights).sum(axis=0)\n            weights = weights[nonnan]\n        else:\n            nans = (~nonnan).sum(axis=0)\n    else:\n        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n\n    if minlength == 0 and max_val is not None:\n        minlength = max_val + 1\n\n    bc = np.bincount(\n        x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n    ).astype(float)\n    # Since `csr_matrix.values` only contain non-zero values or explicit\n    # zeros, we must count implicit zeros separately and add them to the\n    # explicit ones found before\n    if sp.issparse(x_original):\n        # If x contains only NaNs, then bc will be an empty array\n        if zero_weights and bc.size == 0:\n            bc = [zero_weights]\n        elif zero_weights:\n            bc[0] += zero_weights\n\n    return bc, nans",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 82,
                            "end_lineno": 163,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 132,
                            "length": 8
                        },
                        "new_range": {
                            "start": 132,
                            "length": 8
                        },
                        "section": "def bincount(x, weights=None, max_val=None, minlength=0):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        x = x.data",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    x = np.asanyarray(x)",
                                "type": "deleted"
                            },
                            {
                                "content": "    if x.dtype.kind == 'f' and bn.anynan(x):",
                                "type": "deleted"
                            },
                            {
                                "content": "    x = np.asanyarray(x, dtype=float)",
                                "type": "added"
                            },
                            {
                                "content": "    if bn.anynan(x):",
                                "type": "added"
                            },
                            {
                                "content": "        nonnan = ~np.isnan(x)",
                                "type": "context"
                            },
                            {
                                "content": "        x = x[nonnan]",
                                "type": "context"
                            },
                            {
                                "content": "        if weights is not None:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/statistics/util.py",
                            "type": "function",
                            "name": "bincount",
                            "content": "def bincount(x, weights=None, max_val=None, minlength=0):\n    \"\"\"Return counts of values in array X.\n\n    Works kind of like np.bincount(), except that it also supports floating\n    arrays with nans.\n\n    Parameters\n    ----------\n    x : array_like, 1 dimension, nonnegative ints\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same shape as x.\n    max_val : int, optional\n        Indicates the maximum value we expect to find in X and sets the result\n        array size accordingly. E.g. if we set `max_val=2` yet the largest\n        value in X is 1, the result will contain a bin for the value 2, and\n        will be set to 0. See examples for usage.\n    minlength : int, optional\n        A minimum number of bins for the output array. See numpy docs for info.\n\n    Returns\n    -------\n    Tuple[np.ndarray, int]\n        Returns the bincounts and the number of NaN values.\n\n    Examples\n    --------\n    In case `max_val` is provided, the return shape includes bins for these\n    values as well, even if they do not appear in the data. However, this will\n    not truncate the bincount if values larger than `max_count` are found.\n    >>> bincount([0, 0, 1, 1, 2], max_val=4)\n    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n    >>> bincount([0, 1, 2, 3, 4], max_val=2)\n    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n\n    \"\"\"\n    # Store the original matrix before any manipulation to check for sparse\n    x_original = x\n    if sp.issparse(x):\n        if weights is not None:\n            # Match weights and x axis so `indices` will be set appropriately\n            if x.shape[0] == weights.shape[0]:\n                x = x.tocsc()\n            elif x.shape[1] == weights.shape[0]:\n                x = x.tocsr()\n\n            zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n            weights = weights[x.indices]\n        else:\n            zero_weights = sparse_count_implicit_zeros(x)\n\n        x = x.data\n\n    x = np.asanyarray(x)\n    if x.dtype.kind == 'f' and bn.anynan(x):\n        nonnan = ~np.isnan(x)\n        x = x[nonnan]\n        if weights is not None:\n            nans = (~nonnan * weights).sum(axis=0)\n            weights = weights[nonnan]\n        else:\n            nans = (~nonnan).sum(axis=0)\n    else:\n        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n\n    if minlength == 0 and max_val is not None:\n        minlength = max_val + 1\n\n    bc = np.bincount(\n        x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n    ).astype(float)\n    # Since `csr_matrix.values` only contain non-zero values or explicit\n    # zeros, we must count implicit zeros separately and add them to the\n    # explicit ones found before\n    if sp.issparse(x_original):\n        # If x contains only NaNs, then bc will be an empty array\n        if zero_weights and bc.size == 0:\n            bc = [zero_weights]\n        elif zero_weights:\n            bc[0] += zero_weights\n\n    return bc, nans",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 82,
                            "end_lineno": 163,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import unittest\nimport warnings\nfrom distutils.version import LooseVersion\nfrom itertools import chain\nfrom functools import partial, wraps\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix, issparse, lil_matrix, csc_matrix, \\\n    SparseEfficiencyWarning\n\nimport Orange\nfrom Orange.statistics.util import bincount, countnans, contingency, digitize, \\\n    mean, nanmax, nanmean, nanmedian, nanmin, nansum, nanunique, stats, std, \\\n    unique, var, nanstd, nanvar, nanmode, FDR\nfrom sklearn.utils import check_random_state\n\n\ndef dense_sparse(test_case):\n    # type: (Callable) -> Callable\n    \"\"\"Run a single test case on both dense and sparse data.\"\"\"\n    @wraps(test_case)\n    def _wrapper(self):\n\n        def sparse_with_explicit_zero(x, array):\n            \"\"\"Inject one explicit zero into a sparse array.\"\"\"\n            np_array, sp_array = np.atleast_2d(x), array(x)\n            assert issparse(sp_array), 'Can not inject explicit zero into non-sparse matrix'\n\n            zero_indices = np.argwhere(np_array == 0)\n            if zero_indices.size:\n                with warnings.catch_warnings():\n                    # this is just inefficiency in tests, not the tested code\n                    warnings.filterwarnings(\"ignore\", \".*\",\n                                            SparseEfficiencyWarning)\n                    sp_array[tuple(zero_indices[0])] = 0\n\n            return sp_array\n\n        # Make sure to call setUp and tearDown methods in between test runs so\n        # any widget state doesn't interfere between tests\n        def _setup_teardown():\n            self.tearDown()\n            self.setUp()\n\n        test_case(self, np.array)\n        _setup_teardown()\n        test_case(self, csr_matrix)\n        _setup_teardown()\n        test_case(self, csc_matrix)\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csr_matrix))\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csc_matrix))\n\n    return _wrapper\n\n\nclass TestUtil(unittest.TestCase):\n    def setUp(self):\n        nan = float('nan')\n        self.data = [\n            np.array([\n                [0., 1., 0., nan, 3., 5.],\n                [0., 0., nan, nan, 5., nan],\n                [0., 0., 0., nan, 7., 6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    def test_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        cont_table, nans = contingency(x, y, 2, 2)\n        np.testing.assert_equal(cont_table, [[1, 1, 0],\n                                             [1, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_weighted_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        w = np.array([1, 2, 2, 3, 4])\n        cont_table, nans = contingency(x, y, 2, 2, weights=w)\n        np.testing.assert_equal(cont_table, [[1, 2, 0],\n                                             [2, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_stats(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X[1, 1] = np.nan\n        np.testing.assert_equal(stats(X), [[0, 2, 1, 0, 0, 2],\n                                           [1, 1, 1, 0, 1, 1]])\n        # empty table should return ~like metas\n        X = X[:0]\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 0, 0],\n                                           [np.inf, -np.inf, 0, 0, 0, 0]])\n\n    def test_stats_sparse(self):\n        X = csr_matrix(np.identity(5))\n        np.testing.assert_equal(stats(X), [[0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1]])\n\n        # assure last two columns have just zero elements\n        X = X[:3]\n        np.testing.assert_equal(stats(X), [[0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 0, 0, 0, 3, 0],\n                                           [0, 0, 0, 0, 3, 0]])\n\n    def test_stats_weights(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 0, 2],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n        X = np.arange(4).reshape(2, 2).astype(object)\n        np.testing.assert_equal(stats(X, weights), stats(X))\n\n    def test_stats_weights_sparse(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X = csr_matrix(X)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 1, 1],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n    def test_stats_non_numeric(self):\n        X = np.array([\n            [\"\", \"a\", np.nan, 0],\n            [\"a\", \"\", np.nan, 1],\n            [\"a\", \"b\", 0, 0],\n        ], dtype=object)\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 2, 1],\n                                           [np.inf, -np.inf, 0, 0, 0, 3]])\n\n    def test_nanmin_nanmax(self):\n        warnings.filterwarnings(\"ignore\", r\".*All-NaN slice encountered.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            for axis in [None, 0, 1]:\n                np.testing.assert_array_equal(\n                    nanmin(X, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmin(X_sparse, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X_sparse, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n    @dense_sparse\n    def test_nansum(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nansum(X_sparse),\n                np.nansum(X))\n\n    def test_mean(self):\n        # This warning is not unexpected and it's correct\n        warnings.filterwarnings(\"ignore\", r\".*mean\\(\\) resulted in nan.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            np.testing.assert_array_equal(\n                mean(X_sparse),\n                np.mean(X))\n\n        with self.assertWarns(UserWarning):\n            mean([1, np.nan, 0])\n\n    def test_nanmode(self):\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = nanmode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = nanmode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n\n    @dense_sparse\n    def test_nanmedian(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanmedian(X_sparse),\n                np.nanmedian(X))\n\n    @dense_sparse\n    def test_nanmedian_more_nonzeros(self, array):\n        X = np.ones((10, 10))\n        X[:5, 0] = np.nan\n        X[:6, 1] = 0\n        X_sparse = array(X)\n        np.testing.assert_array_equal(\n            nanmedian(X_sparse),\n            np.nanmedian(X)\n        )\n\n    def test_var(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    var(csr_matrix(data), axis=axis),\n                    np.var(data, axis=axis)\n                )\n\n    def test_var_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.var(x, axis=axis, ddof=10),\n                var(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanvar(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanvar(X_sparse),\n                np.nanvar(X))\n\n    def test_nanvar_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        np.fill_diagonal(x, np.nan)\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanvar(x, axis=axis, ddof=10),\n                nanvar(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_std(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    std(csr_matrix(data), axis=axis),\n                    np.std(data, axis=axis)\n                )\n\n    def test_std_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.std(x, axis=axis, ddof=10),\n                std(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanstd(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanstd(X_sparse),\n                np.nanstd(X))\n\n    def test_nanstd_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanstd(x, axis=axis, ddof=10),\n                nanstd(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_FDR(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            FDR(p_values), decimal=5)\n\n    def test_FDR_dependent(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00076, 0.00091, 0.00011, 0.00086, 0.00057]),\n            FDR(p_values, dependent=True), decimal=5)\n\n    def test_FDR_m(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.0002, 0.00024, 0.00003, 0.000225, 0.00015]),\n            FDR(p_values, m=3), decimal=5)\n\n    def test_FDR_no_values(self):\n        self.assertIsNone(FDR(None))\n        self.assertIsNone(FDR([]))\n        self.assertIsNone(FDR([0.0002, 0.0004], m=0))\n\n    def test_FDR_list(self):\n        p_values = [0.0002, 0.0004, 0.00001, 0.0003, 0.0001]\n        result = FDR(p_values)\n        self.assertIsInstance(result, list)\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            result, decimal=5)\n\n    def test_array_equal_deprecated(self):\n        \"\"\"This test is to be included in the 3.22 release and will fail in\n        version 3.24. This serves as a reminder to remove the deprecated method\n        and this test.\"\"\"\n        if LooseVersion(Orange.__version__) >= LooseVersion(\"3.24\"):\n            self.fail(\n                \"`Orange.statistics.util.array_equal` was deprecated in \"\n                \"version 3.22, and there have been two minor versions in \"\n                \"between. Please remove the deprecated method from the module.\"\n            )\n\n\nclass TestNanmean(unittest.TestCase):\n    def setUp(self):\n        self.random_state = check_random_state(42)\n        self.x = self.random_state.uniform(size=(10, 5))\n        np.fill_diagonal(self.x, np.nan)\n\n    @dense_sparse\n    def test_axis_none(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x), nanmean(array(self.x))\n        )\n\n    @dense_sparse\n    def test_axis_0(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=0), nanmean(array(self.x), axis=0)\n        )\n\n    @dense_sparse\n    def test_axis_1(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=1), nanmean(array(self.x), axis=1)\n        )\n\n\nclass TestDigitize(unittest.TestCase):\n    def setUp(self):\n        # pylint: disable=bad-whitespace\n        self.data = [\n            np.array([\n                [0., 1.,     0., np.nan, 3.,     5.],\n                [0., 0., np.nan, np.nan, 5., np.nan],\n                [0., 0.,     0., np.nan, 7.,     6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    @dense_sparse\n    def test_digitize(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins).reshape(x_shape),\n                digitize(x, bins),\n            )\n\n    @dense_sparse\n    def test_digitize_right(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins, right=True).reshape(x_shape),\n                digitize(x, bins, right=True)\n            )\n\n    @dense_sparse\n    def test_digitize_1d_array(self, array):\n        \"\"\"A consistent return shape must be returned for both sparse and dense.\"\"\"\n        x_original = np.array([0, 1, 1, 0, np.nan, 0, 1])\n        x = array(x_original)\n        bins = np.arange(-2, 2)\n\n        x_shape = x_original.shape\n        np.testing.assert_array_equal(\n            [np.digitize(x_original.flatten(), bins).reshape(x_shape)],\n            digitize(x, bins),\n        )\n\n    def test_digitize_sparse_zeroth_bin(self):\n        # Setup the data so that the '0's will fit into the '0'th bin.\n        data = csr_matrix([\n            [0, 0, 0, 1, 1, 0, 0, 1, 0],\n            [0, 0, 1, 1, 0, 0, 1, 0, 0],\n        ])\n        bins = np.array([1])\n        # Then digitize should return a sparse matrix\n        self.assertTrue(issparse(digitize(data, bins)))\n\n\nclass TestCountnans(unittest.TestCase):\n    @dense_sparse\n    def test_1d_array(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        self.assertEqual(countnans(x), 2)\n\n    @dense_sparse\n    def test_1d_array_with_axis_0(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        expected = 2\n\n        self.assertEqual(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_1d_array_with_axis_1_raises_exception(self, array):\n        with self.assertRaises(ValueError):\n            countnans(array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1]), axis=1)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = 4\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_0(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, np.nan, 3, 3]])\n        expected = [0, 0, 0, 0, 1, 1, 0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_1(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = [2, 2]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_2d_matrix(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = 2\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_on_columns(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_on_rows(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [1, 1]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_1d_weights_with_axis_0(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1, 1, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=0), [.5, 0, 1, 0])\n\n    @dense_sparse\n    def test_1d_weights_with_axis_1(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=1), [.5, 1])\n\n    @dense_sparse\n    def test_2d_weights(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[np.nan, np.nan, 1,      1 ],\n                   [     0, np.nan, 2, np.nan ]])\n        w = np.array([[1, 2, 3, 4],\n                      [5, 6, 7, 8]])\n\n        np.testing.assert_equal(countnans(x, w), 17)\n        np.testing.assert_equal(countnans(x, w, axis=0), [1, 8, 0, 8])\n        np.testing.assert_equal(countnans(x, w, axis=1), [3, 14])\n\n    @dense_sparse\n    def test_dtype(self, array):\n        x = array([0, np.nan, 2, 3])\n        w = np.array([0, 1.5, 0, 0])\n\n        self.assertIsInstance(countnans(x, w, dtype=np.int32), np.int32)\n        self.assertEqual(countnans(x, w, dtype=np.int32), 1)\n        self.assertIsInstance(countnans(x, w, dtype=np.float64), np.float64)\n        self.assertEqual(countnans(x, w, dtype=np.float64), 1.5)\n\n\nclass TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n\nclass TestUnique(unittest.TestCase):\n    @dense_sparse\n    def test_returns_unique_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7, np.nan, np.nan]\n\n        np.testing.assert_equal(unique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_returns_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1, 1, 1]\n\n        np.testing.assert_equal(unique(x, return_counts=True)[1], expected)\n\n    def test_sparse_explicit_zeros(self):\n        # Use `lil_matrix` to fix sparse warning for matrix construction\n        x = lil_matrix(np.eye(3))\n        x[0, 1] = 0\n        x[1, 0] = 0\n        x = x.tocsr()\n        # Test against identity matrix\n        y = csr_matrix(np.eye(3))\n\n        np.testing.assert_array_equal(\n            unique(y, return_counts=True),\n            unique(x, return_counts=True),\n        )\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7]\n\n        np.testing.assert_equal(nanunique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1]\n\n        np.testing.assert_equal(nanunique(x, return_counts=True)[1], expected)\n\n\nclass TestNanModeFixedInScipy(unittest.TestCase):\n\n    @unittest.expectedFailure\n    def test_scipy_nanmode_still_wrong(self):\n        import scipy.stats\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = scipy.stats.mode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = scipy.stats.mode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n        # When Scipy's scipy.stats.mode works correcly, remove Orange.statistics.util.nanmode\n        # and this test. Also update requirements.\n",
            "new_file_content": "import unittest\nimport warnings\nfrom distutils.version import LooseVersion\nfrom itertools import chain\nfrom functools import partial, wraps\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix, issparse, lil_matrix, csc_matrix, \\\n    SparseEfficiencyWarning\n\nimport Orange\nfrom Orange.statistics.util import bincount, countnans, contingency, digitize, \\\n    mean, nanmax, nanmean, nanmedian, nanmin, nansum, nanunique, stats, std, \\\n    unique, var, nanstd, nanvar, nanmode, FDR\nfrom sklearn.utils import check_random_state\n\n\ndef dense_sparse(test_case):\n    # type: (Callable) -> Callable\n    \"\"\"Run a single test case on both dense and sparse data.\"\"\"\n    @wraps(test_case)\n    def _wrapper(self):\n\n        def sparse_with_explicit_zero(x, array):\n            \"\"\"Inject one explicit zero into a sparse array.\"\"\"\n            np_array, sp_array = np.atleast_2d(x), array(x)\n            assert issparse(sp_array), 'Can not inject explicit zero into non-sparse matrix'\n\n            zero_indices = np.argwhere(np_array == 0)\n            if zero_indices.size:\n                with warnings.catch_warnings():\n                    # this is just inefficiency in tests, not the tested code\n                    warnings.filterwarnings(\"ignore\", \".*\",\n                                            SparseEfficiencyWarning)\n                    sp_array[tuple(zero_indices[0])] = 0\n\n            return sp_array\n\n        # Make sure to call setUp and tearDown methods in between test runs so\n        # any widget state doesn't interfere between tests\n        def _setup_teardown():\n            self.tearDown()\n            self.setUp()\n\n        test_case(self, np.array)\n        _setup_teardown()\n        test_case(self, csr_matrix)\n        _setup_teardown()\n        test_case(self, csc_matrix)\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csr_matrix))\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csc_matrix))\n\n    return _wrapper\n\n\nclass TestUtil(unittest.TestCase):\n    def setUp(self):\n        nan = float('nan')\n        self.data = [\n            np.array([\n                [0., 1., 0., nan, 3., 5.],\n                [0., 0., nan, nan, 5., nan],\n                [0., 0., 0., nan, 7., 6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    def test_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        cont_table, nans = contingency(x, y, 2, 2)\n        np.testing.assert_equal(cont_table, [[1, 1, 0],\n                                             [1, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_weighted_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        w = np.array([1, 2, 2, 3, 4])\n        cont_table, nans = contingency(x, y, 2, 2, weights=w)\n        np.testing.assert_equal(cont_table, [[1, 2, 0],\n                                             [2, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_stats(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X[1, 1] = np.nan\n        np.testing.assert_equal(stats(X), [[0, 2, 1, 0, 0, 2],\n                                           [1, 1, 1, 0, 1, 1]])\n        # empty table should return ~like metas\n        X = X[:0]\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 0, 0],\n                                           [np.inf, -np.inf, 0, 0, 0, 0]])\n\n    def test_stats_sparse(self):\n        X = csr_matrix(np.identity(5))\n        np.testing.assert_equal(stats(X), [[0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1]])\n\n        # assure last two columns have just zero elements\n        X = X[:3]\n        np.testing.assert_equal(stats(X), [[0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 0, 0, 0, 3, 0],\n                                           [0, 0, 0, 0, 3, 0]])\n\n    def test_stats_weights(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 0, 2],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n        X = np.arange(4).reshape(2, 2).astype(object)\n        np.testing.assert_equal(stats(X, weights), stats(X))\n\n    def test_stats_weights_sparse(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X = csr_matrix(X)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 1, 1],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n    def test_stats_non_numeric(self):\n        X = np.array([\n            [\"\", \"a\", np.nan, 0],\n            [\"a\", \"\", np.nan, 1],\n            [\"a\", \"b\", 0, 0],\n        ], dtype=object)\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 2, 1],\n                                           [np.inf, -np.inf, 0, 0, 0, 3]])\n\n    def test_nanmin_nanmax(self):\n        warnings.filterwarnings(\"ignore\", r\".*All-NaN slice encountered.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            for axis in [None, 0, 1]:\n                np.testing.assert_array_equal(\n                    nanmin(X, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmin(X_sparse, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X_sparse, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n    @dense_sparse\n    def test_nansum(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nansum(X_sparse),\n                np.nansum(X))\n\n    def test_mean(self):\n        # This warning is not unexpected and it's correct\n        warnings.filterwarnings(\"ignore\", r\".*mean\\(\\) resulted in nan.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            np.testing.assert_array_equal(\n                mean(X_sparse),\n                np.mean(X))\n\n        with self.assertWarns(UserWarning):\n            mean([1, np.nan, 0])\n\n    def test_nanmode(self):\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = nanmode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = nanmode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n\n    @dense_sparse\n    def test_nanmedian(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanmedian(X_sparse),\n                np.nanmedian(X))\n\n    @dense_sparse\n    def test_nanmedian_more_nonzeros(self, array):\n        X = np.ones((10, 10))\n        X[:5, 0] = np.nan\n        X[:6, 1] = 0\n        X_sparse = array(X)\n        np.testing.assert_array_equal(\n            nanmedian(X_sparse),\n            np.nanmedian(X)\n        )\n\n    def test_var(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    var(csr_matrix(data), axis=axis),\n                    np.var(data, axis=axis)\n                )\n\n    def test_var_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.var(x, axis=axis, ddof=10),\n                var(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanvar(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanvar(X_sparse),\n                np.nanvar(X))\n\n    def test_nanvar_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        np.fill_diagonal(x, np.nan)\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanvar(x, axis=axis, ddof=10),\n                nanvar(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_std(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    std(csr_matrix(data), axis=axis),\n                    np.std(data, axis=axis)\n                )\n\n    def test_std_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.std(x, axis=axis, ddof=10),\n                std(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanstd(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanstd(X_sparse),\n                np.nanstd(X))\n\n    def test_nanstd_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanstd(x, axis=axis, ddof=10),\n                nanstd(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_FDR(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            FDR(p_values), decimal=5)\n\n    def test_FDR_dependent(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00076, 0.00091, 0.00011, 0.00086, 0.00057]),\n            FDR(p_values, dependent=True), decimal=5)\n\n    def test_FDR_m(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.0002, 0.00024, 0.00003, 0.000225, 0.00015]),\n            FDR(p_values, m=3), decimal=5)\n\n    def test_FDR_no_values(self):\n        self.assertIsNone(FDR(None))\n        self.assertIsNone(FDR([]))\n        self.assertIsNone(FDR([0.0002, 0.0004], m=0))\n\n    def test_FDR_list(self):\n        p_values = [0.0002, 0.0004, 0.00001, 0.0003, 0.0001]\n        result = FDR(p_values)\n        self.assertIsInstance(result, list)\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            result, decimal=5)\n\n    def test_array_equal_deprecated(self):\n        \"\"\"This test is to be included in the 3.22 release and will fail in\n        version 3.24. This serves as a reminder to remove the deprecated method\n        and this test.\"\"\"\n        if LooseVersion(Orange.__version__) >= LooseVersion(\"3.24\"):\n            self.fail(\n                \"`Orange.statistics.util.array_equal` was deprecated in \"\n                \"version 3.22, and there have been two minor versions in \"\n                \"between. Please remove the deprecated method from the module.\"\n            )\n\n\nclass TestNanmean(unittest.TestCase):\n    def setUp(self):\n        self.random_state = check_random_state(42)\n        self.x = self.random_state.uniform(size=(10, 5))\n        np.fill_diagonal(self.x, np.nan)\n\n    @dense_sparse\n    def test_axis_none(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x), nanmean(array(self.x))\n        )\n\n    @dense_sparse\n    def test_axis_0(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=0), nanmean(array(self.x), axis=0)\n        )\n\n    @dense_sparse\n    def test_axis_1(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=1), nanmean(array(self.x), axis=1)\n        )\n\n\nclass TestDigitize(unittest.TestCase):\n    def setUp(self):\n        # pylint: disable=bad-whitespace\n        self.data = [\n            np.array([\n                [0., 1.,     0., np.nan, 3.,     5.],\n                [0., 0., np.nan, np.nan, 5., np.nan],\n                [0., 0.,     0., np.nan, 7.,     6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    @dense_sparse\n    def test_digitize(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins).reshape(x_shape),\n                digitize(x, bins),\n            )\n\n    @dense_sparse\n    def test_digitize_right(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins, right=True).reshape(x_shape),\n                digitize(x, bins, right=True)\n            )\n\n    @dense_sparse\n    def test_digitize_1d_array(self, array):\n        \"\"\"A consistent return shape must be returned for both sparse and dense.\"\"\"\n        x_original = np.array([0, 1, 1, 0, np.nan, 0, 1])\n        x = array(x_original)\n        bins = np.arange(-2, 2)\n\n        x_shape = x_original.shape\n        np.testing.assert_array_equal(\n            [np.digitize(x_original.flatten(), bins).reshape(x_shape)],\n            digitize(x, bins),\n        )\n\n    def test_digitize_sparse_zeroth_bin(self):\n        # Setup the data so that the '0's will fit into the '0'th bin.\n        data = csr_matrix([\n            [0, 0, 0, 1, 1, 0, 0, 1, 0],\n            [0, 0, 1, 1, 0, 0, 1, 0, 0],\n        ])\n        bins = np.array([1])\n        # Then digitize should return a sparse matrix\n        self.assertTrue(issparse(digitize(data, bins)))\n\n\nclass TestCountnans(unittest.TestCase):\n    @dense_sparse\n    def test_1d_array(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        self.assertEqual(countnans(x), 2)\n\n    @dense_sparse\n    def test_1d_array_with_axis_0(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        expected = 2\n\n        self.assertEqual(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_1d_array_with_axis_1_raises_exception(self, array):\n        with self.assertRaises(ValueError):\n            countnans(array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1]), axis=1)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = 4\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_0(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, np.nan, 3, 3]])\n        expected = [0, 0, 0, 0, 1, 1, 0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_1(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = [2, 2]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_2d_matrix(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = 2\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_on_columns(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_on_rows(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [1, 1]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_1d_weights_with_axis_0(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1, 1, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=0), [.5, 0, 1, 0])\n\n    @dense_sparse\n    def test_1d_weights_with_axis_1(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=1), [.5, 1])\n\n    @dense_sparse\n    def test_2d_weights(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[np.nan, np.nan, 1,      1 ],\n                   [     0, np.nan, 2, np.nan ]])\n        w = np.array([[1, 2, 3, 4],\n                      [5, 6, 7, 8]])\n\n        np.testing.assert_equal(countnans(x, w), 17)\n        np.testing.assert_equal(countnans(x, w, axis=0), [1, 8, 0, 8])\n        np.testing.assert_equal(countnans(x, w, axis=1), [3, 14])\n\n    @dense_sparse\n    def test_dtype(self, array):\n        x = array([0, np.nan, 2, 3])\n        w = np.array([0, 1.5, 0, 0])\n\n        self.assertIsInstance(countnans(x, w, dtype=np.int32), np.int32)\n        self.assertEqual(countnans(x, w, dtype=np.int32), 1)\n        self.assertIsInstance(countnans(x, w, dtype=np.float64), np.float64)\n        self.assertEqual(countnans(x, w, dtype=np.float64), 1.5)\n\n\nclass TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    # object arrays cannot be converted to sparse, so test only for dense\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n\nclass TestUnique(unittest.TestCase):\n    @dense_sparse\n    def test_returns_unique_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7, np.nan, np.nan]\n\n        np.testing.assert_equal(unique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_returns_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1, 1, 1]\n\n        np.testing.assert_equal(unique(x, return_counts=True)[1], expected)\n\n    def test_sparse_explicit_zeros(self):\n        # Use `lil_matrix` to fix sparse warning for matrix construction\n        x = lil_matrix(np.eye(3))\n        x[0, 1] = 0\n        x[1, 0] = 0\n        x = x.tocsr()\n        # Test against identity matrix\n        y = csr_matrix(np.eye(3))\n\n        np.testing.assert_array_equal(\n            unique(y, return_counts=True),\n            unique(x, return_counts=True),\n        )\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7]\n\n        np.testing.assert_equal(nanunique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1]\n\n        np.testing.assert_equal(nanunique(x, return_counts=True)[1], expected)\n\n\nclass TestNanModeFixedInScipy(unittest.TestCase):\n\n    @unittest.expectedFailure\n    def test_scipy_nanmode_still_wrong(self):\n        import scipy.stats\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = scipy.stats.mode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = scipy.stats.mode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n        # When Scipy's scipy.stats.mode works correcly, remove Orange.statistics.util.nanmode\n        # and this test. Also update requirements.\n",
            "header": {
                "file": {
                    "path": "Orange/tests/test_statistics.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "d5442d789",
                "new_commit_hash": "d13b9503b",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/tests/test_statistics.py"
            },
            "plus_file": {
                "path": "b/Orange/tests/test_statistics.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 517,
                            "length": 6
                        },
                        "new_range": {
                            "start": 517,
                            "length": 13
                        },
                        "section": "class TestBincount(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        np.testing.assert_equal(bincount(x)[1], expected)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    # object arrays cannot be converted to sparse, so test only for dense",
                                "type": "added"
                            },
                            {
                                "content": "    def test_count_nans_objectarray(self):",
                                "type": "added"
                            },
                            {
                                "content": "        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)",
                                "type": "added"
                            },
                            {
                                "content": "        expected = 1",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        np.testing.assert_equal(bincount(x)[1], expected)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @dense_sparse",
                                "type": "context"
                            },
                            {
                                "content": "    def test_adds_empty_bins(self, array):",
                                "type": "context"
                            },
                            {
                                "content": "        x = array([0, 1, 3, 5])",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/tests/test_statistics.py",
                            "type": "class",
                            "name": "TestBincount",
                            "content": "class TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    # object arrays cannot be converted to sparse, so test only for dense\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 512,
                            "end_lineno": 596,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "Orange/tests/test_statistics.py",
                            "type": "method",
                            "name": "TestBincount.test_count_nans_objectarray",
                            "content": "class TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    # object arrays cannot be converted to sparse, so test only for dense\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 521,
                            "end_lineno": 525,
                            "parent": {
                                "file_name": "Orange/tests/test_statistics.py",
                                "type": "class",
                                "name": "TestBincount",
                                "content": "class TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    # object arrays cannot be converted to sparse, so test only for dense\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 512,
                                "end_lineno": 596,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9^",
    "new_commit_hash": "1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9",
    "commit_message": "util: Fix bincount for object arrays",
    "commit_date": "2019-05-30T11:36:53+02:00",
    "metadata": {}
}
{
    "repo_name": "orange3",
    "new_commit_hash": "1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9",
    "test_file_codes": [
        "import unittest\nimport warnings\nfrom distutils.version import LooseVersion\nfrom itertools import chain\nfrom functools import partial, wraps\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix, issparse, lil_matrix, csc_matrix, \\\n    SparseEfficiencyWarning\n\nimport Orange\nfrom Orange.statistics.util import bincount, countnans, contingency, digitize, \\\n    mean, nanmax, nanmean, nanmedian, nanmin, nansum, nanunique, stats, std, \\\n    unique, var, nanstd, nanvar, nanmode, FDR\nfrom sklearn.utils import check_random_state\n\n\ndef dense_sparse(test_case):\n    # type: (Callable) -> Callable\n    \"\"\"Run a single test case on both dense and sparse data.\"\"\"\n    @wraps(test_case)\n    def _wrapper(self):\n\n        def sparse_with_explicit_zero(x, array):\n            \"\"\"Inject one explicit zero into a sparse array.\"\"\"\n            np_array, sp_array = np.atleast_2d(x), array(x)\n            assert issparse(sp_array), 'Can not inject explicit zero into non-sparse matrix'\n\n            zero_indices = np.argwhere(np_array == 0)\n            if zero_indices.size:\n                with warnings.catch_warnings():\n                    # this is just inefficiency in tests, not the tested code\n                    warnings.filterwarnings(\"ignore\", \".*\",\n                                            SparseEfficiencyWarning)\n                    sp_array[tuple(zero_indices[0])] = 0\n\n            return sp_array\n\n        # Make sure to call setUp and tearDown methods in between test runs so\n        # any widget state doesn't interfere between tests\n        def _setup_teardown():\n            self.tearDown()\n            self.setUp()\n\n        test_case(self, np.array)\n        _setup_teardown()\n        test_case(self, csr_matrix)\n        _setup_teardown()\n        test_case(self, csc_matrix)\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csr_matrix))\n        _setup_teardown()\n        test_case(self, partial(sparse_with_explicit_zero, array=csc_matrix))\n\n    return _wrapper\n\n\nclass TestUtil(unittest.TestCase):\n    def setUp(self):\n        nan = float('nan')\n        self.data = [\n            np.array([\n                [0., 1., 0., nan, 3., 5.],\n                [0., 0., nan, nan, 5., nan],\n                [0., 0., 0., nan, 7., 6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    def test_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        cont_table, nans = contingency(x, y, 2, 2)\n        np.testing.assert_equal(cont_table, [[1, 1, 0],\n                                             [1, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_weighted_contingency(self):\n        x = np.array([0, 1, 0, 2, np.nan])\n        y = np.array([0, 0, 1, np.nan, 0])\n        w = np.array([1, 2, 2, 3, 4])\n        cont_table, nans = contingency(x, y, 2, 2, weights=w)\n        np.testing.assert_equal(cont_table, [[1, 2, 0],\n                                             [2, 0, 0],\n                                             [0, 0, 0]])\n        np.testing.assert_equal(nans, [1, 0, 0])\n\n    def test_stats(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X[1, 1] = np.nan\n        np.testing.assert_equal(stats(X), [[0, 2, 1, 0, 0, 2],\n                                           [1, 1, 1, 0, 1, 1]])\n        # empty table should return ~like metas\n        X = X[:0]\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 0, 0],\n                                           [np.inf, -np.inf, 0, 0, 0, 0]])\n\n    def test_stats_sparse(self):\n        X = csr_matrix(np.identity(5))\n        np.testing.assert_equal(stats(X), [[0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1],\n                                           [0, 1, .2, 0, 4, 1]])\n\n        # assure last two columns have just zero elements\n        X = X[:3]\n        np.testing.assert_equal(stats(X), [[0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 1, 1/3, 0, 2, 1],\n                                           [0, 0, 0, 0, 3, 0],\n                                           [0, 0, 0, 0, 3, 0]])\n\n    def test_stats_weights(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 0, 2],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n        X = np.arange(4).reshape(2, 2).astype(object)\n        np.testing.assert_equal(stats(X, weights), stats(X))\n\n    def test_stats_weights_sparse(self):\n        X = np.arange(4).reshape(2, 2).astype(float)\n        X = csr_matrix(X)\n        weights = np.array([1, 3])\n        np.testing.assert_equal(stats(X, weights), [[0, 2, 1.5, 0, 1, 1],\n                                                    [1, 3, 2.5, 0, 0, 2]])\n\n    def test_stats_non_numeric(self):\n        X = np.array([\n            [\"\", \"a\", np.nan, 0],\n            [\"a\", \"\", np.nan, 1],\n            [\"a\", \"b\", 0, 0],\n        ], dtype=object)\n        np.testing.assert_equal(stats(X), [[np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 1, 2],\n                                           [np.inf, -np.inf, 0, 0, 2, 1],\n                                           [np.inf, -np.inf, 0, 0, 0, 3]])\n\n    def test_nanmin_nanmax(self):\n        warnings.filterwarnings(\"ignore\", r\".*All-NaN slice encountered.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            for axis in [None, 0, 1]:\n                np.testing.assert_array_equal(\n                    nanmin(X, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmin(X_sparse, axis=axis),\n                    np.nanmin(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n                np.testing.assert_array_equal(\n                    nanmax(X_sparse, axis=axis),\n                    np.nanmax(X, axis=axis))\n\n    @dense_sparse\n    def test_nansum(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nansum(X_sparse),\n                np.nansum(X))\n\n    def test_mean(self):\n        # This warning is not unexpected and it's correct\n        warnings.filterwarnings(\"ignore\", r\".*mean\\(\\) resulted in nan.*\")\n        for X in self.data:\n            X_sparse = csr_matrix(X)\n            np.testing.assert_array_equal(\n                mean(X_sparse),\n                np.mean(X))\n\n        with self.assertWarns(UserWarning):\n            mean([1, np.nan, 0])\n\n    def test_nanmode(self):\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = nanmode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = nanmode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n\n    @dense_sparse\n    def test_nanmedian(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanmedian(X_sparse),\n                np.nanmedian(X))\n\n    @dense_sparse\n    def test_nanmedian_more_nonzeros(self, array):\n        X = np.ones((10, 10))\n        X[:5, 0] = np.nan\n        X[:6, 1] = 0\n        X_sparse = array(X)\n        np.testing.assert_array_equal(\n            nanmedian(X_sparse),\n            np.nanmedian(X)\n        )\n\n    def test_var(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    var(csr_matrix(data), axis=axis),\n                    np.var(data, axis=axis)\n                )\n\n    def test_var_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.var(x, axis=axis, ddof=10),\n                var(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanvar(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanvar(X_sparse),\n                np.nanvar(X))\n\n    def test_nanvar_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        np.fill_diagonal(x, np.nan)\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanvar(x, axis=axis, ddof=10),\n                nanvar(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_std(self):\n        for data in self.data:\n            for axis in chain((None,), range(len(data.shape))):\n                # Can't use array_equal here due to differences on 1e-16 level\n                np.testing.assert_array_almost_equal(\n                    std(csr_matrix(data), axis=axis),\n                    np.std(data, axis=axis)\n                )\n\n    def test_std_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.std(x, axis=axis, ddof=10),\n                std(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    @dense_sparse\n    def test_nanstd(self, array):\n        for X in self.data:\n            X_sparse = array(X)\n            np.testing.assert_array_equal(\n                nanstd(X_sparse),\n                np.nanstd(X))\n\n    def test_nanstd_with_ddof(self):\n        x = np.random.uniform(0, 10, (20, 100))\n        for axis in [None, 0, 1]:\n            np.testing.assert_almost_equal(\n                np.nanstd(x, axis=axis, ddof=10),\n                nanstd(csr_matrix(x), axis=axis, ddof=10),\n            )\n\n    def test_FDR(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            FDR(p_values), decimal=5)\n\n    def test_FDR_dependent(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.00076, 0.00091, 0.00011, 0.00086, 0.00057]),\n            FDR(p_values, dependent=True), decimal=5)\n\n    def test_FDR_m(self):\n        p_values = np.array([0.0002, 0.0004, 0.00001, 0.0003, 0.0001])\n        np.testing.assert_almost_equal(\n            np.array([0.0002, 0.00024, 0.00003, 0.000225, 0.00015]),\n            FDR(p_values, m=3), decimal=5)\n\n    def test_FDR_no_values(self):\n        self.assertIsNone(FDR(None))\n        self.assertIsNone(FDR([]))\n        self.assertIsNone(FDR([0.0002, 0.0004], m=0))\n\n    def test_FDR_list(self):\n        p_values = [0.0002, 0.0004, 0.00001, 0.0003, 0.0001]\n        result = FDR(p_values)\n        self.assertIsInstance(result, list)\n        np.testing.assert_almost_equal(\n            np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),\n            result, decimal=5)\n\n    def test_array_equal_deprecated(self):\n        \"\"\"This test is to be included in the 3.22 release and will fail in\n        version 3.24. This serves as a reminder to remove the deprecated method\n        and this test.\"\"\"\n        if LooseVersion(Orange.__version__) >= LooseVersion(\"3.24\"):\n            self.fail(\n                \"`Orange.statistics.util.array_equal` was deprecated in \"\n                \"version 3.22, and there have been two minor versions in \"\n                \"between. Please remove the deprecated method from the module.\"\n            )\n\n\nclass TestNanmean(unittest.TestCase):\n    def setUp(self):\n        self.random_state = check_random_state(42)\n        self.x = self.random_state.uniform(size=(10, 5))\n        np.fill_diagonal(self.x, np.nan)\n\n    @dense_sparse\n    def test_axis_none(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x), nanmean(array(self.x))\n        )\n\n    @dense_sparse\n    def test_axis_0(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=0), nanmean(array(self.x), axis=0)\n        )\n\n    @dense_sparse\n    def test_axis_1(self, array):\n        np.testing.assert_almost_equal(\n            np.nanmean(self.x, axis=1), nanmean(array(self.x), axis=1)\n        )\n\n\nclass TestDigitize(unittest.TestCase):\n    def setUp(self):\n        # pylint: disable=bad-whitespace\n        self.data = [\n            np.array([\n                [0., 1.,     0., np.nan, 3.,     5.],\n                [0., 0., np.nan, np.nan, 5., np.nan],\n                [0., 0.,     0., np.nan, 7.,     6.]]),\n            np.zeros((2, 3)),\n            np.ones((2, 3)),\n        ]\n\n    @dense_sparse\n    def test_digitize(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins).reshape(x_shape),\n                digitize(x, bins),\n            )\n\n    @dense_sparse\n    def test_digitize_right(self, array):\n        for x_original in self.data:\n            x = array(x_original)\n            bins = np.arange(-2, 2)\n\n            x_shape = x.shape\n            np.testing.assert_array_equal(\n                np.digitize(x_original.flatten(), bins, right=True).reshape(x_shape),\n                digitize(x, bins, right=True)\n            )\n\n    @dense_sparse\n    def test_digitize_1d_array(self, array):\n        \"\"\"A consistent return shape must be returned for both sparse and dense.\"\"\"\n        x_original = np.array([0, 1, 1, 0, np.nan, 0, 1])\n        x = array(x_original)\n        bins = np.arange(-2, 2)\n\n        x_shape = x_original.shape\n        np.testing.assert_array_equal(\n            [np.digitize(x_original.flatten(), bins).reshape(x_shape)],\n            digitize(x, bins),\n        )\n\n    def test_digitize_sparse_zeroth_bin(self):\n        # Setup the data so that the '0's will fit into the '0'th bin.\n        data = csr_matrix([\n            [0, 0, 0, 1, 1, 0, 0, 1, 0],\n            [0, 0, 1, 1, 0, 0, 1, 0, 0],\n        ])\n        bins = np.array([1])\n        # Then digitize should return a sparse matrix\n        self.assertTrue(issparse(digitize(data, bins)))\n\n\nclass TestCountnans(unittest.TestCase):\n    @dense_sparse\n    def test_1d_array(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        self.assertEqual(countnans(x), 2)\n\n    @dense_sparse\n    def test_1d_array_with_axis_0(self, array):\n        x = array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1])\n        expected = 2\n\n        self.assertEqual(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_1d_array_with_axis_1_raises_exception(self, array):\n        with self.assertRaises(ValueError):\n            countnans(array([0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1]), axis=1)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = 4\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_0(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, np.nan, 3, 3]])\n        expected = [0, 0, 0, 0, 1, 1, 0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_shape_matches_dense_and_sparse_with_axis_1(self, array):\n        x = array([[0, 1, 0, 2, 2, np.nan, 1, np.nan, 0, 1],\n                   [1, 2, 2, 1, np.nan, 1, 2, 3, np.nan, 3]])\n        expected = [2, 2]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_2d_matrix(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = 2\n\n        self.assertEqual(countnans(x), expected)\n\n    @dense_sparse\n    def test_on_columns(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [0, 2, 0, 0]\n\n        np.testing.assert_equal(countnans(x, axis=0), expected)\n\n    @dense_sparse\n    def test_on_rows(self, array):\n        x = array([[1, np.nan, 1, 2],\n                   [2, np.nan, 2, 3]])\n        expected = [1, 1]\n\n        np.testing.assert_equal(countnans(x, axis=1), expected)\n\n    @dense_sparse\n    def test_1d_weights_with_axis_0(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1, 1, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=0), [.5, 0, 1, 0])\n\n    @dense_sparse\n    def test_1d_weights_with_axis_1(self, array):\n        x = array([[1, 1, np.nan, 1],\n                   [np.nan, 1, 1, 1]])\n        w = np.array([0.5, 1])\n\n        np.testing.assert_equal(countnans(x, w, axis=1), [.5, 1])\n\n    @dense_sparse\n    def test_2d_weights(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[np.nan, np.nan, 1,      1 ],\n                   [     0, np.nan, 2, np.nan ]])\n        w = np.array([[1, 2, 3, 4],\n                      [5, 6, 7, 8]])\n\n        np.testing.assert_equal(countnans(x, w), 17)\n        np.testing.assert_equal(countnans(x, w, axis=0), [1, 8, 0, 8])\n        np.testing.assert_equal(countnans(x, w, axis=1), [3, 14])\n\n    @dense_sparse\n    def test_dtype(self, array):\n        x = array([0, np.nan, 2, 3])\n        w = np.array([0, 1.5, 0, 0])\n\n        self.assertIsInstance(countnans(x, w, dtype=np.int32), np.int32)\n        self.assertEqual(countnans(x, w, dtype=np.int32), 1)\n        self.assertIsInstance(countnans(x, w, dtype=np.float64), np.float64)\n        self.assertEqual(countnans(x, w, dtype=np.float64), 1.5)\n\n\nclass TestBincount(unittest.TestCase):\n    @dense_sparse\n    def test_count_nans(self, array):\n        x = array([0, 0, 1, 2, np.nan, 2])\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    # object arrays cannot be converted to sparse, so test only for dense\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n\n        np.testing.assert_equal(bincount(x)[1], expected)\n\n    @dense_sparse\n    def test_adds_empty_bins(self, array):\n        x = array([0, 1, 3, 5])\n        expected = [1, 1, 0, 1, 0, 1]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_maxval_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 5\n        expected = [0, 3, 2, 1, 0, 0]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_maxval_doesnt_truncate_values_when_too_small(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        max_val = 1\n        expected = [0, 3, 2, 1]\n\n        np.testing.assert_equal(bincount(x, max_val=max_val)[0], expected)\n\n    @dense_sparse\n    def test_minlength_adds_empty_bins(self, array):\n        x = array([1, 1, 1, 2, 3, 2])\n        minlength = 5\n        expected = [0, 3, 2, 1, 0]\n\n        np.testing.assert_equal(bincount(x, minlength=minlength)[0], expected)\n\n    @dense_sparse\n    def test_weights(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_nans(self, array):\n        x = array([0, 0, 1, 1, np.nan, 2, np.nan, 3])\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 1, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_weights_with_transposed_x(self, array):\n        x = array([0, 0, 1, 1, 2, 2, 3, 3]).T\n        w = np.array([1, 2, 0, 0, 1, 1, 0, 1])\n\n        expected = [3, 0, 2, 1]\n        np.testing.assert_equal(bincount(x, w)[0], expected)\n\n    @dense_sparse\n    def test_all_nans(self, array):\n        x = array([np.nan] * 5)\n        expected = []\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n    @dense_sparse\n    def test_all_zeros_or_nans(self, array):\n        \"\"\"Sparse arrays with only nans with no explicit zeros will have no non\n        zero indices. Check that this counts the zeros properly.\"\"\"\n        x = array([np.nan] * 5 + [0] * 5)\n        expected = [5]\n\n        np.testing.assert_equal(bincount(x)[0], expected)\n\n\nclass TestUnique(unittest.TestCase):\n    @dense_sparse\n    def test_returns_unique_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7, np.nan, np.nan]\n\n        np.testing.assert_equal(unique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_returns_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1, 1, 1]\n\n        np.testing.assert_equal(unique(x, return_counts=True)[1], expected)\n\n    def test_sparse_explicit_zeros(self):\n        # Use `lil_matrix` to fix sparse warning for matrix construction\n        x = lil_matrix(np.eye(3))\n        x[0, 1] = 0\n        x[1, 0] = 0\n        x = x.tocsr()\n        # Test against identity matrix\n        y = csr_matrix(np.eye(3))\n\n        np.testing.assert_array_equal(\n            unique(y, return_counts=True),\n            unique(x, return_counts=True),\n        )\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_values(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [-1, 0, 1, 2, 3, 5, 6, 7]\n\n        np.testing.assert_equal(nanunique(x, return_counts=False), expected)\n\n    @dense_sparse\n    def test_nanunique_ignores_nans_in_counts(self, array):\n        # pylint: disable=bad-whitespace\n        x = array([[-1., 1., 0., 2., 3., np.nan],\n                   [ 0., 0., 0., 3., 5., np.nan],\n                   [-1., 0., 0., 1., 7.,     6.]])\n        expected = [2, 6, 2, 1, 2, 1, 1, 1]\n\n        np.testing.assert_equal(nanunique(x, return_counts=True)[1], expected)\n\n\nclass TestNanModeFixedInScipy(unittest.TestCase):\n\n    @unittest.expectedFailure\n    def test_scipy_nanmode_still_wrong(self):\n        import scipy.stats\n        X = np.array([[np.nan, np.nan, 1, 1],\n                      [2, np.nan, 1, 1]])\n        mode, count = scipy.stats.mode(X, 0)\n        np.testing.assert_array_equal(mode, [[2, np.nan, 1, 1]])\n        np.testing.assert_array_equal(count, [[1, np.nan, 2, 2]])\n        mode, count = scipy.stats.mode(X, 1)\n        np.testing.assert_array_equal(mode, [[1], [1]])\n        np.testing.assert_array_equal(count, [[2], [2]])\n        # When Scipy's scipy.stats.mode works correcly, remove Orange.statistics.util.nanmode\n        # and this test. Also update requirements.\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Orange installation attempts...\nAttempting installation with Python 3.7...\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nrunning build_ext\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpbwij2jj9/tmp\ncreating /tmp/tmpbwij2jj9/tmp/tmpbwij2jj9\ncompile options: '-MMD -MF /tmp/tmpbwij2jj9/file.c.d -c'\ncc: /tmp/tmpbwij2jj9/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmp5wc9688n/tmp\ncreating /tmp/tmp5wc9688n/tmp/tmp5wc9688n\ncompile options: '-MMD -MF /tmp/tmp5wc9688n/file.c.d -c'\ncc: /tmp/tmp5wc9688n/file.c\ncustomize UnixCCompiler using build_ext\nbuilding 'Orange.classification._simple_tree' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange\ncreating build/temp.linux-x86_64-3.7/Orange/classification\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_simple_tree.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_simple_tree.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_simple_tree.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.classification._tree_scorers' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_tree_scorers.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_tree_scorers.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_tree_scorers.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._valuecount' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/data\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_valuecount.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_valuecount.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_valuecount.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._contingency' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_contingency.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_contingency.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_contingency.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._io' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_io.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_io.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_io.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._variable' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_variable.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_variable.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_variable.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.distance._distance' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/distance\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/distance/_distance.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/distance/_distance.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/distance/_distance.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._discretize' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/preprocess\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/preprocess/_discretize.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_discretize.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_discretize.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._relieff' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/preprocess/_relieff.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_relieff.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_relieff.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.widgets.utils._grid_density' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/widgets\ncreating build/temp.linux-x86_64-3.7/Orange/widgets/utils\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/widgets/utils/_grid_density.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/widgets/utils/_grid_density.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/widgets/utils/_grid_density.cpython-37m-x86_64-linux-gnu.so\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nrunning develop\nrunning build_scripts\nrunning egg_info\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncreating Orange3.egg-info\nwriting Orange3.egg-info/PKG-INFO\nwriting dependency_links to Orange3.egg-info/dependency_links.txt\nwriting entry points to Orange3.egg-info/entry_points.txt\nwriting requirements to Orange3.egg-info/requires.txt\nwriting top-level names to Orange3.egg-info/top_level.txt\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest template 'MANIFEST.in'\nwarning: no files found matching 'README*' under directory 'Orange'\nwarning: no files found matching 'LICENSE' under directory 'Orange'\nwarning: no files found matching '*.basket' under directory 'Orange/datasets'\nwarning: no files found matching '*.html' under directory 'Orange/canvas'\nwarning: no files found matching '*.css' under directory 'Orange/widgets'\nwarning: no files found matching 'COPYING'\nadding license file 'LICENSE'\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nrunning build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpi24ailp5/tmp\ncreating /tmp/tmpi24ailp5/tmp/tmpi24ailp5\ncompile options: '-MMD -MF /tmp/tmpi24ailp5/file.c.d -c'\ncc: /tmp/tmpi24ailp5/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpsohsh0tv/tmp\ncreating /tmp/tmpsohsh0tv/tmp/tmpsohsh0tv\ncompile options: '-MMD -MF /tmp/tmpsohsh0tv/file.c.d -c'\ncc: /tmp/tmpsohsh0tv/file.c\ncustomize UnixCCompiler using build_ext\nCreating /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/Orange3.egg-link (link to .)\nAdding Orange3 3.22.0.dev0+1c914f6 to easy-install.pth file\nInstalling orange-canvas script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nInstalled /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9\nProcessing dependencies for Orange3==3.22.0.dev0+1c914f6\nSearching for XlsxWriter==3.2.0\nBest match: XlsxWriter 3.2.0\nAdding XlsxWriter 3.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for xlrd==2.0.1\nBest match: xlrd 2.0.1\nAdding xlrd 2.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for setuptools==59.8.0\nBest match: setuptools 59.8.0\nAdding setuptools 59.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for serverfiles==0.3.1\nBest match: serverfiles 0.3.1\nAdding serverfiles 0.3.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for scipy==1.7.3\nBest match: scipy 1.7.3\nAdding scipy 1.7.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for scikit-learn==1.0.2\nBest match: scikit-learn 1.0.2\nAdding scikit-learn 1.0.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for requests==2.31.0\nBest match: requests 2.31.0\nAdding requests 2.31.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for python-louvain==0.16\nBest match: python-louvain 0.16\nAdding python-louvain 0.16 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for pyqtgraph==0.12.4\nBest match: pyqtgraph 0.12.4\nAdding pyqtgraph 0.12.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for pip==24.0\nBest match: pip 24.0\nAdding pip 24.0 to easy-install.pth file\nInstalling pip script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling pip3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling pip3.10 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for openTSNE==1.0.1\nBest match: openTSNE 1.0.1\nAdding openTSNE 1.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for numpy==1.17.5\nBest match: numpy 1.17.5\nAdding numpy 1.17.5 to easy-install.pth file\nInstalling f2py script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling f2py3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling f2py3.7 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for networkx==2.6.3\nBest match: networkx 2.6.3\nAdding networkx 2.6.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for matplotlib==3.5.3\nBest match: matplotlib 3.5.3\nAdding matplotlib 3.5.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for keyrings.alt==4.2.0\nBest match: keyrings.alt 4.2.0\nAdding keyrings.alt 4.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for keyring==24.1.1\nBest match: keyring 24.1.1\nAdding keyring 24.1.1 to easy-install.pth file\nInstalling keyring script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for joblib==1.3.2\nBest match: joblib 1.3.2\nAdding joblib 1.3.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for docutils==0.20.1\nBest match: docutils 0.20.1\nAdding docutils 0.20.1 to easy-install.pth file\nInstalling docutils script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for chardet==5.2.0\nBest match: chardet 5.2.0\nAdding chardet 5.2.0 to easy-install.pth file\nInstalling chardetect script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for Bottleneck==1.4.0\nBest match: Bottleneck 1.4.0\nAdding Bottleneck 1.4.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for AnyQt==0.2.0\nBest match: AnyQt 0.2.0\nAdding AnyQt 0.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for threadpoolctl==3.1.0\nBest match: threadpoolctl 3.1.0\nAdding threadpoolctl 3.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for charset-normalizer==3.4.1\nBest match: charset-normalizer 3.4.1\nAdding charset-normalizer 3.4.1 to easy-install.pth file\nInstalling normalizer script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for idna==3.10\nBest match: idna 3.10\nAdding idna 3.10 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for certifi==2024.12.14\nBest match: certifi 2024.12.14\nAdding certifi 2024.12.14 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for urllib3==2.0.7\nBest match: urllib3 2.0.7\nAdding urllib3 2.0.7 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for cycler==0.11.0\nBest match: cycler 0.11.0\nAdding cycler 0.11.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for Pillow==9.5.0\nBest match: Pillow 9.5.0\nAdding Pillow 9.5.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for kiwisolver==1.4.5\nBest match: kiwisolver 1.4.5\nAdding kiwisolver 1.4.5 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for pyparsing==3.1.4\nBest match: pyparsing 3.1.4\nAdding pyparsing 3.1.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for python-dateutil==2.9.0.post0\nBest match: python-dateutil 2.9.0.post0\nAdding python-dateutil 2.9.0.post0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for packaging==24.0\nBest match: packaging 24.0\nAdding packaging 24.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for fonttools==4.38.0\nBest match: fonttools 4.38.0\nAdding fonttools 4.38.0 to easy-install.pth file\nInstalling fonttools script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling pyftmerge script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling pyftsubset script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\nInstalling ttx script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for jaraco.classes==3.2.3\nBest match: jaraco.classes 3.2.3\nAdding jaraco.classes 3.2.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for importlib-resources==5.12.0\nBest match: importlib-resources 5.12.0\nAdding importlib-resources 5.12.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for SecretStorage==3.3.3\nBest match: SecretStorage 3.3.3\nAdding SecretStorage 3.3.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for jeepney==0.8.0\nBest match: jeepney 0.8.0\nAdding jeepney 0.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for importlib-metadata==6.7.0\nBest match: importlib-metadata 6.7.0\nAdding importlib-metadata 6.7.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for typing-extensions==4.7.1\nBest match: typing-extensions 4.7.1\nAdding typing-extensions 4.7.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for six==1.17.0\nBest match: six 1.17.0\nAdding six 1.17.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for more-itertools==9.1.0\nBest match: more-itertools 9.1.0\nAdding more-itertools 9.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for zipp==3.15.0\nBest match: zipp 3.15.0\nAdding zipp 3.15.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for cryptography==44.0.0\nBest match: cryptography 44.0.0\nAdding cryptography 44.0.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for cffi==1.15.1\nBest match: cffi 1.15.1\nAdding cffi 1.15.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nSearching for pycparser==2.21\nBest match: pycparser 2.21\nAdding pycparser 2.21 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages\nFinished processing dependencies for Orange3==3.22.0.dev0+1c914f6\nVerifying Orange installation...\n✅ Orange installation successful!\nSuccessfully installed orange using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 18 packages in 141ms\nPrepared 18 packages in 40ms\nInstalled 18 packages in 511ms\n + cython==0.29.37\n + exceptiongroup==1.2.2\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + numpy==1.17.5\n + packaging==24.0\n + pluggy==1.2.0\n + pyqt5==5.15.10\n + pyqt5-qt5==5.15.16\n + pyqt5-sip==12.13.0\n + pyqtwebengine==5.15.6\n + pyqtwebengine-qt5==5.15.16\n + pytest==7.4.4\n + setuptools==59.8.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + wheel==0.42.0\n + zipp==3.15.0\nResolved 33 packages in 148ms\nInstalled 28 packages in 581ms\n + bottleneck==1.4.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + chardet==5.2.0\n + charset-normalizer==3.4.1\n + cryptography==44.0.0\n + idna==3.10\n + importlib-resources==5.12.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + joblib==1.3.2\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + more-itertools==9.1.0\n + networkx==2.6.3\n + opentsne==1.0.1\n + pip==24.0\n + pycparser==2.21\n + python-louvain==0.16\n + requests==2.31.0\n + scikit-learn==1.0.2\n + scipy==1.7.3\n + secretstorage==3.3.3\n + serverfiles==0.3.1\n + threadpoolctl==3.1.0\n + urllib3==2.0.7\n + xlrd==2.0.1\n + xlsxwriter==3.2.0\nResolved 14 packages in 92ms\nInstalled 11 packages in 26ms\n + anyqt==0.2.0\n + cycler==0.11.0\n + docutils==0.20.1\n + fonttools==4.38.0\n + kiwisolver==1.4.5\n + matplotlib==3.5.3\n + pillow==9.5.0\n + pyparsing==3.1.4\n + pyqtgraph==0.12.4\n + python-dateutil==2.9.0.post0\n + six==1.17.0\nResolved 2 packages in 8ms\nInstalled 2 packages in 29ms\n + psycopg2==2.9.9\n + pymssql==2.3.2\nResolved 5 packages in 17ms\nInstalled 2 packages in 90ms\n + pandas==1.3.5\n + pytz==2024.2\nAudited 2 packages in 1ms\nOrange/classification/_simple_tree.c: In function ‘gain_ratio_c’:\nOrange/classification/_simple_tree.c:63:9: warning: implicit declaration of function ‘qsort_r’; did you mean ‘qsort’? [-Wimplicit-function-declaration]\n   63 |         qsort_r(base, nel, size, compar, thunk)\n      |         ^~~~~~~\nOrange/classification/_simple_tree.c:147:9: note: in expansion of macro ‘QSORT_R_FUNC’\n  147 |         QSORT_R_FUNC(examples, size, sizeof(struct Example), (void*) &compar_attr, compar_examples);\n      |         ^~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/classification/_tree_scorers.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_2find_threshold_entropy’:\nOrange/classification/_tree_scorers.c:3115:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 3115 |   __pyx_t_7 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_6find_threshold_MSE’:\nOrange/classification/_tree_scorers.c:4619:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 4619 |   __pyx_t_1 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_8find_binarization_MSE’:\nOrange/classification/_tree_scorers.c:5396:43: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5396 |           for (__pyx_t_22 = 0; __pyx_t_22 < __pyx_t_21; __pyx_t_22+=1) {\n      |                                           ^\nOrange/classification/_tree_scorers.c:5517:39: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5517 |           __pyx_t_27 = ((__pyx_v_left >= __pyx_v_min_leaf) != 0);\n      |                                       ^~\nOrange/classification/_tree_scorers.c:5523:53: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5523 |           __pyx_t_27 = (((__pyx_v_N - __pyx_v_left) >= __pyx_v_min_leaf) != 0);\n      |                                                     ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_14compute_predictions_csr’:\nOrange/classification/_tree_scorers.c:7051:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7051 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_16compute_predictions_csc’:\nOrange/classification/_tree_scorers.c:7741:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7741 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c:7801:143: warning: comparison of integer expressions of different signedness: ‘__pyx_t_5numpy_int32_t’ {aka ‘int’} and ‘unsigned int’ [-Wsign-compare]\n 7801 |               __pyx_t_17 = (((*((__pyx_t_5numpy_int32_t *) ( /* dim=0 */ (__pyx_v_indices.data + __pyx_t_18 * __pyx_v_indices.strides[0]) ))) != __pyx_v_i) != 0);\n      |                                                                                                                                               ^~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_valuecount.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_contingency.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/data/_io.c: In function ‘__pyx_pf_6Orange_4data_3_io_sparse_read_float.constprop’:\nOrange/data/_io.c:3881:24: warning: ‘__pyx_v_decs’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3881 |           __pyx_v_decs = (__pyx_v_decs / 10.0);\n      |           ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:4070:24: warning: ‘__pyx_v_value’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4070 |           __pyx_t_10 = PyFloat_FromDouble(__pyx_v_value); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 221, __pyx_L5_error)\n      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:480:40: warning: ‘__pyx_v_attr_index’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n  480 |   #define PyInt_FromLong               PyLong_FromLong\n      |                                        ^~~~~~~~~~~~~~~\nOrange/data/_io.c:1301:7: note: ‘__pyx_v_attr_index’ was declared here\n 1301 |   int __pyx_v_attr_index;\n      |       ^~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:2935:25: warning: ‘__pyx_v_atomp’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2935 |           __pyx_v_atomp = (__pyx_v_atomp + 1);\n      |           ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/distance/_distance.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_discretize.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_relieff.cpp:581:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/setuptools/command/easy_install.py:159: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.\n  EasyInstallDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9/.venv/lib/python3.7/site-packages/setuptools/command/egg_info.py:628: SetuptoolsDeprecationWarning: Custom 'build_py' does not implement 'get_data_files_without_manifest'.\nPlease extend command classes from setuptools instead of distutils.\n  SetuptoolsDeprecationWarning\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9\ncollected 64 items\n\nr2e_tests/test_1.py .................................................... [ 81%]\n...........x                                                             [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_dependent\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_list\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_m\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_no_values\nPASSED r2e_tests/test_1.py::TestUtil::test_array_equal_deprecated\nPASSED r2e_tests/test_1.py::TestUtil::test_contingency\nPASSED r2e_tests/test_1.py::TestUtil::test_mean\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmedian\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmedian_more_nonzeros\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmin_nanmax\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmode\nPASSED r2e_tests/test_1.py::TestUtil::test_nanstd\nPASSED r2e_tests/test_1.py::TestUtil::test_nanstd_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_nansum\nPASSED r2e_tests/test_1.py::TestUtil::test_nanvar\nPASSED r2e_tests/test_1.py::TestUtil::test_nanvar_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_stats\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_non_numeric\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_sparse\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_weights\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_weights_sparse\nPASSED r2e_tests/test_1.py::TestUtil::test_std\nPASSED r2e_tests/test_1.py::TestUtil::test_std_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_var\nPASSED r2e_tests/test_1.py::TestUtil::test_var_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_weighted_contingency\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_0\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_1\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_none\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_1d_array\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_right\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_sparse_zeroth_bin\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array_with_axis_1_raises_exception\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_weights_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_weights_with_axis_1\nPASSED r2e_tests/test_1.py::TestCountnans::test_2d_matrix\nPASSED r2e_tests/test_1.py::TestCountnans::test_2d_weights\nPASSED r2e_tests/test_1.py::TestCountnans::test_dtype\nPASSED r2e_tests/test_1.py::TestCountnans::test_on_columns\nPASSED r2e_tests/test_1.py::TestCountnans::test_on_rows\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse_with_axis_1\nPASSED r2e_tests/test_1.py::TestBincount::test_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_all_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_all_zeros_or_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_count_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_count_nans_objectarray\nPASSED r2e_tests/test_1.py::TestBincount::test_maxval_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_maxval_doesnt_truncate_values_when_too_small\nPASSED r2e_tests/test_1.py::TestBincount::test_minlength_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_weights\nPASSED r2e_tests/test_1.py::TestBincount::test_weights_with_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_weights_with_transposed_x\nPASSED r2e_tests/test_1.py::TestUnique::test_nanunique_ignores_nans_in_counts\nPASSED r2e_tests/test_1.py::TestUnique::test_nanunique_ignores_nans_in_values\nPASSED r2e_tests/test_1.py::TestUnique::test_returns_counts\nPASSED r2e_tests/test_1.py::TestUnique::test_returns_unique_values\nPASSED r2e_tests/test_1.py::TestUnique::test_sparse_explicit_zeros\nXFAIL r2e_tests/test_1.py::TestNanModeFixedInScipy::test_scipy_nanmode_still_wrong - reason: \n======================== 63 passed, 1 xfailed in 1.30s =========================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1c914f6f2f8af2f597a04fc3ed549cb8e963d4a9\ncollected 64 items\n\nr2e_tests/test_1.py ...................................................F [ 81%]\n...........x                                                             [100%]\n\n=================================== FAILURES ===================================\n___________________ TestBincount.test_count_nans_objectarray ___________________\n\nself = <r2e_tests.test_1.TestBincount testMethod=test_count_nans_objectarray>\n\n    def test_count_nans_objectarray(self):\n        x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)\n        expected = 1\n    \n>       np.testing.assert_equal(bincount(x)[1], expected)\n\nr2e_tests/test_1.py:525: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nx = array([0, 0, 1, 2, nan, 2], dtype=object), weights = None, max_val = None\nminlength = 0\n\n    def bincount(x, weights=None, max_val=None, minlength=0):\n        \"\"\"Return counts of values in array X.\n    \n        Works kind of like np.bincount(), except that it also supports floating\n        arrays with nans.\n    \n        Parameters\n        ----------\n        x : array_like, 1 dimension, nonnegative ints\n            Input array.\n        weights : array_like, optional\n            Weights, array of the same shape as x.\n        max_val : int, optional\n            Indicates the maximum value we expect to find in X and sets the result\n            array size accordingly. E.g. if we set `max_val=2` yet the largest\n            value in X is 1, the result will contain a bin for the value 2, and\n            will be set to 0. See examples for usage.\n        minlength : int, optional\n            A minimum number of bins for the output array. See numpy docs for info.\n    \n        Returns\n        -------\n        Tuple[np.ndarray, int]\n            Returns the bincounts and the number of NaN values.\n    \n        Examples\n        --------\n        In case `max_val` is provided, the return shape includes bins for these\n        values as well, even if they do not appear in the data. However, this will\n        not truncate the bincount if values larger than `max_count` are found.\n        >>> bincount([0, 0, 1, 1, 2], max_val=4)\n        (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n        >>> bincount([0, 1, 2, 3, 4], max_val=2)\n        (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n    \n        \"\"\"\n        # Store the original matrix before any manipulation to check for sparse\n        x_original = x\n        if sp.issparse(x):\n            if weights is not None:\n                # Match weights and x axis so `indices` will be set appropriately\n                if x.shape[0] == weights.shape[0]:\n                    x = x.tocsc()\n                elif x.shape[1] == weights.shape[0]:\n                    x = x.tocsr()\n    \n                zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n                weights = weights[x.indices]\n            else:\n                zero_weights = sparse_count_implicit_zeros(x)\n    \n            x = x.data\n    \n        x = np.asanyarray(x)\n        if x.dtype.kind == 'f' and bn.anynan(x):\n            nonnan = ~np.isnan(x)\n            x = x[nonnan]\n            if weights is not None:\n                nans = (~nonnan * weights).sum(axis=0)\n                weights = weights[nonnan]\n            else:\n                nans = (~nonnan).sum(axis=0)\n        else:\n            nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n    \n        if minlength == 0 and max_val is not None:\n            minlength = max_val + 1\n    \n        bc = np.bincount(\n>           x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n        ).astype(float)\nE       ValueError: cannot convert float NaN to integer\n\nOrange/statistics/util.py:151: ValueError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_dependent\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_list\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_m\nPASSED r2e_tests/test_1.py::TestUtil::test_FDR_no_values\nPASSED r2e_tests/test_1.py::TestUtil::test_array_equal_deprecated\nPASSED r2e_tests/test_1.py::TestUtil::test_contingency\nPASSED r2e_tests/test_1.py::TestUtil::test_mean\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmedian\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmedian_more_nonzeros\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmin_nanmax\nPASSED r2e_tests/test_1.py::TestUtil::test_nanmode\nPASSED r2e_tests/test_1.py::TestUtil::test_nanstd\nPASSED r2e_tests/test_1.py::TestUtil::test_nanstd_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_nansum\nPASSED r2e_tests/test_1.py::TestUtil::test_nanvar\nPASSED r2e_tests/test_1.py::TestUtil::test_nanvar_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_stats\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_non_numeric\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_sparse\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_weights\nPASSED r2e_tests/test_1.py::TestUtil::test_stats_weights_sparse\nPASSED r2e_tests/test_1.py::TestUtil::test_std\nPASSED r2e_tests/test_1.py::TestUtil::test_std_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_var\nPASSED r2e_tests/test_1.py::TestUtil::test_var_with_ddof\nPASSED r2e_tests/test_1.py::TestUtil::test_weighted_contingency\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_0\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_1\nPASSED r2e_tests/test_1.py::TestNanmean::test_axis_none\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_1d_array\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_right\nPASSED r2e_tests/test_1.py::TestDigitize::test_digitize_sparse_zeroth_bin\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_array_with_axis_1_raises_exception\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_weights_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_1d_weights_with_axis_1\nPASSED r2e_tests/test_1.py::TestCountnans::test_2d_matrix\nPASSED r2e_tests/test_1.py::TestCountnans::test_2d_weights\nPASSED r2e_tests/test_1.py::TestCountnans::test_dtype\nPASSED r2e_tests/test_1.py::TestCountnans::test_on_columns\nPASSED r2e_tests/test_1.py::TestCountnans::test_on_rows\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse_with_axis_0\nPASSED r2e_tests/test_1.py::TestCountnans::test_shape_matches_dense_and_sparse_with_axis_1\nPASSED r2e_tests/test_1.py::TestBincount::test_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_all_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_all_zeros_or_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_count_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_maxval_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_maxval_doesnt_truncate_values_when_too_small\nPASSED r2e_tests/test_1.py::TestBincount::test_minlength_adds_empty_bins\nPASSED r2e_tests/test_1.py::TestBincount::test_weights\nPASSED r2e_tests/test_1.py::TestBincount::test_weights_with_nans\nPASSED r2e_tests/test_1.py::TestBincount::test_weights_with_transposed_x\nPASSED r2e_tests/test_1.py::TestUnique::test_nanunique_ignores_nans_in_counts\nPASSED r2e_tests/test_1.py::TestUnique::test_nanunique_ignores_nans_in_values\nPASSED r2e_tests/test_1.py::TestUnique::test_returns_counts\nPASSED r2e_tests/test_1.py::TestUnique::test_returns_unique_values\nPASSED r2e_tests/test_1.py::TestUnique::test_sparse_explicit_zeros\nXFAIL r2e_tests/test_1.py::TestNanModeFixedInScipy::test_scipy_nanmode_still_wrong - reason: \nFAILED r2e_tests/test_1.py::TestBincount::test_count_nans_objectarray - Value...\n=================== 1 failed, 62 passed, 1 xfailed in 1.43s ====================\n",
    "old_commit_res_stderr": ""
}
Orange/statistics/util.py Orange/tests/test_statistics.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `bincount` Raises ValueError for Object Arrays Containing NaNs

**Description:**
When using the `bincount` function with object arrays that include `NaN` values, a `ValueError` is thrown. This error occurs because the function attempts to convert `NaN` values to integers, which is not possible. As a result, counting occurrences in such arrays fails unexpectedly.

**Example Code:**
```python
import numpy as np
from Orange.statistics.util import bincount

x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)
result = bincount(x)
print(result[1])  # Expected to count the number of NaNs
```

**Expected Behavior:**
The `bincount` function should correctly handle object arrays containing `NaN` values by counting the non-NaN integers and separately tracking the number of `NaN` occurrences without raising an error.

**Actual Behavior:**
A `ValueError` is raised with the message: `cannot convert float NaN to integer`, preventing the function from completing the count.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/statistics/util.py
"""
This module provides alternatives for the few additional functions found in
and once used from the bottlechest package (fork of bottleneck).

It also patches bottleneck to contain these functions.
"""
import warnings
from typing import Iterable

import bottleneck as bn
import numpy as np
import scipy.stats.stats
from scipy import sparse as sp

from sklearn.utils.sparsefuncs import mean_variance_axis

from Orange.data.util import array_equal
from Orange.util import deprecated

# For backwards compatibility
array_equal = deprecated("Orange.data.util.array_equal")(array_equal)


def _count_nans_per_row_sparse(X, weights, dtype=None):
    """ Count the number of nans (undefined) values per row. """
    if weights is not None:
        X = X.tocoo(copy=False)
        nonzero_mask = np.isnan(X.data)
        nan_rows, nan_cols = X.row[nonzero_mask], X.col[nonzero_mask]

        if weights.ndim == 1:
            data_weights = weights[nan_rows]
        else:
            data_weights = weights[nan_rows, nan_cols]

        w = sp.coo_matrix((data_weights, (nan_rows, nan_cols)), shape=X.shape)
        w = w.tocsr()
        return np.asarray(w.sum(axis=1), dtype=dtype).ravel()

    if isinstance(X, (sp.csr_matrix, sp.csc_matrix)):
        X = type(X)((np.isnan(X.data), X.indices, X.indptr), X.shape)
        return np.asarray(X.sum(axis=1), dtype=dtype).ravel()
    else:  # pragma: no cover
        raise TypeError("unsupported type '{}'".format(type(X).__name__))


def sparse_count_implicit_zeros(x):
    """ Count the number of implicit zeros in a sparse matrix. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')
    return np.prod(x.shape) - x.nnz


def sparse_has_implicit_zeros(x):
    """ Check if sparse matrix contains any implicit zeros. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')
    return np.prod(x.shape) != x.nnz


def sparse_implicit_zero_weights(x, weights):
    """ Extract the weight values of all zeros in a sparse matrix. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')

    if weights.ndim == 1:
        # Match weights and x axis so `indices` will be set appropriately
        if x.shape[0] == weights.shape[0]:
            x = x.tocsc()
        elif x.shape[1] == weights.shape[0]:
            x = x.tocsr()
        n_items = np.prod(x.shape)
        zero_indices = np.setdiff1d(np.arange(n_items), x.indices, assume_unique=True)
        return weights[zero_indices]
    else:
        # Can easily be implemented using a coo_matrix
        raise NotImplementedError(
            'Computing zero weights on ndimensinal weight matrix is not implemented'
        )


def bincount(x, weights=None, max_val=None, minlength=0):
    """Return counts of values in array X.

    Works kind of like np.bincount(), except that it also supports floating
    arrays with nans.

    Parameters
    ----------
    x : array_like, 1 dimension, nonnegative ints
        Input array.
    weights : array_like, optional
        Weights, array of the same shape as x.
    max_val : int, optional
        Indicates the maximum value we expect to find in X and sets the result
        array size accordingly. E.g. if we set `max_val=2` yet the largest
        value in X is 1, the result will contain a bin for the value 2, and
        will be set to 0. See examples for usage.
    minlength : int, optional
        A minimum number of bins for the output array. See numpy docs for info.

    Returns
    -------
    Tuple[np.ndarray, int]
        Returns the bincounts and the number of NaN values.

    Examples
    --------
    In case `max_val` is provided, the return shape includes bins for these
    values as well, even if they do not appear in the data. However, this will
    not truncate the bincount if values larger than `max_count` are found.
    >>> bincount([0, 0, 1, 1, 2], max_val=4)
    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)
    >>> bincount([0, 1, 2, 3, 4], max_val=2)
    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)

    """
    # Store the original matrix before any manipulation to check for sparse
    x_original = x
    if sp.issparse(x):
        if weights is not None:
            # Match weights and x axis so `indices` will be set appropriately
            if x.shape[0] == weights.shape[0]:
                x = x.tocsc()
            elif x.shape[1] == weights.shape[0]:
                x = x.tocsr()

            zero_weights = sparse_implicit_zero_weights(x, weights).sum()
            weights = weights[x.indices]
        else:
            zero_weights = sparse_count_implicit_zeros(x)

        x = x.data

    x = np.asanyarray(x)
    if x.dtype.kind == 'f' and bn.anynan(x):
        nonnan = ~np.isnan(x)
        x = x[nonnan]
        if weights is not None:
            nans = (~nonnan * weights).sum(axis=0)
            weights = weights[nonnan]
        else:
            nans = (~nonnan).sum(axis=0)
    else:
        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)

    if minlength == 0 and max_val is not None:
        minlength = max_val + 1

    bc = np.bincount(
        x.astype(np.int32, copy=False), weights=weights, minlength=minlength
    ).astype(float)
    # Since `csr_matrix.values` only contain non-zero values or explicit
    # zeros, we must count implicit zeros separately and add them to the
    # explicit ones found before
    if sp.issparse(x_original):
        # If x contains only NaNs, then bc will be an empty array
        if zero_weights and bc.size == 0:
            bc = [zero_weights]
        elif zero_weights:
            bc[0] += zero_weights

    return bc, nans


def countnans(x, weights=None, axis=None, dtype=None, keepdims=False):
    """
    Count the undefined elements in an array along given axis.

    Parameters
    ----------
    x : array_like
    weights : array_like, optional
        Weights to weight the nans with, before or after counting (depending
        on the weights shape).
    axis : int, optional
    dtype : dtype, optional
        The data type of the returned array.

    Returns
    -------
    Union[np.ndarray, float]

    """
    if not sp.issparse(x):
        x = np.asanyarray(x)
        isnan = np.isnan(x)
        if weights is not None and weights.shape == x.shape:
            isnan = isnan * weights

        counts = isnan.sum(axis=axis, dtype=dtype, keepdims=keepdims)
        if weights is not None and weights.shape != x.shape:
            counts = counts * weights
    else:
        assert axis in [None, 0, 1], 'Only axis 0 and 1 are currently supported'
        # To have consistent behaviour with dense matrices, raise error when
        # `axis=1` and the array is 1d (e.g. [[1 2 3]])
        if x.shape[0] == 1 and axis == 1:
            raise ValueError('Axis %d is out of bounds' % axis)

        arr = x if axis == 1 else x.T

        if weights is not None:
            weights = weights if axis == 1 else weights.T

        arr = arr.tocsr()
        counts = _count_nans_per_row_sparse(arr, weights, dtype=dtype)

        # We want a scalar value if `axis=None` or if the sparse matrix is
        # actually a vector (e.g. [[1 2 3]]), but has `ndim=2` due to scipy
        # implementation
        if axis is None or x.shape[0] == 1:
            counts = counts.sum(dtype=dtype)

    return counts


def contingency(X, y, max_X=None, max_y=None, weights=None, mask=None):
    """
    Compute the contingency matrices for each column of X (excluding the masked)
    versus the vector y.

    If the array is 1-dimensional, a 2d contingency matrix is returned. If the
    array is 2d, the function returns a 3d array, with the first dimension
    corresponding to column index (variable in the input array).

    The rows of contingency matrix correspond to values of variables, the
    columns correspond to values in vector `y`.
    (??? isn't it the other way around ???)

    Rows in the input array can be weighted (argument `weights`). A subset of
    columns can be selected by additional argument `mask`.

    The function also returns a count of NaN values per each value of `y`.

    Parameters
    ----------
    X : array_like
        With values in columns.
    y : 1d array
        Vector of true values.
    max_X : int
        The maximal value in the array
    max_y : int
        The maximal value in `y`
    weights : array_like
        Row weights. When not None, contingencies contain weighted counts
    mask : sequence
        Discrete columns of X.

    Returns
    -------
    contingencies: (m × ny × nx) array
        m number of masked (used) columns (all if mask=None), i.e.
        for each column of X;
        ny number of uniques in y,
        nx number of uniques in column of X.
    nans : array_like
        Number of nans in each column of X for each unique value of y.
    """
    was_1d = False
    if X.ndim == 1:
        X = X[..., np.newaxis]
        was_1d = True

    contingencies, nans = [], []
    ny = np.unique(y).size if max_y is None else max_y + 1
    for i in range(X.shape[1]):
        if mask is not None and not mask[i]:
            contingencies.append(np.zeros((ny, max_X + 1)))
            nans.append(np.zeros(ny))
            continue
        col = X[..., i]
        nx = np.unique(col[~np.isnan(col)]).size if max_X is None else max_X + 1
        if sp.issparse(col):
            col = np.ravel(col.todense())
        contingencies.append(
            bincount(y + ny * col,
                     minlength=ny * nx,
                     weights=weights)[0].reshape(nx, ny).T)
        nans.append(
            bincount(y[np.isnan(col)], minlength=ny)[0])
    if was_1d:
        return contingencies[0], nans[0]
    return np.array(contingencies), np.array(nans)


def stats(X, weights=None, compute_variance=False):
    """
    Compute min, max, #nans, mean and variance.

    Result is a tuple (min, max, mean, variance, #nans, #non-nans) or an
    array of shape (len(X), 6).

    The mean and the number of nans and non-nans are weighted.

    Computation of variance requires an additional pass and is not enabled
    by default. Zeros are filled in instead of variance.

    Parameters
    ----------
    X : array_like, 1 or 2 dimensions
        Input array.
    weights : array_like, optional
        Weights, array of the same length as `x`.
    compute_variance : bool, optional
        If set to True, the function also computes variance.

    Returns
    -------
    out : a 6-element tuple or an array of shape (len(x), 6)
        Computed (min, max, mean, variance or 0, #nans, #non-nans)

    Raises
    ------
    ValueError
        If the length of the weight vector does not match the length of the
        array
    """
    is_numeric = np.issubdtype(X.dtype, np.number)
    is_sparse = sp.issparse(X)
    weighted = weights is not None and X.dtype != object

    def weighted_mean():
        if is_sparse:
            w_X = X.multiply(sp.csr_matrix(np.c_[weights] / sum(weights)))
            return np.asarray(w_X.sum(axis=0)).ravel()
        else:
            return np.nansum(X * np.c_[weights] / sum(weights), axis=0)

    if X.size and is_numeric and not is_sparse:
        nans = np.isnan(X).sum(axis=0)
        return np.column_stack((
            np.nanmin(X, axis=0),
            np.nanmax(X, axis=0),
            np.nanmean(X, axis=0) if not weighted else weighted_mean(),
            np.nanvar(X, axis=0) if compute_variance else np.zeros(X.shape[1]),
            nans,
            X.shape[0] - nans))
    elif is_sparse and X.size:
        if compute_variance:
            raise NotImplementedError

        non_zero = np.bincount(X.nonzero()[1], minlength=X.shape[1])
        X = X.tocsc()
        return np.column_stack((
            nanmin(X, axis=0),
            nanmax(X, axis=0),
            nanmean(X, axis=0) if not weighted else weighted_mean(),
            np.zeros(X.shape[1]),      # variance not supported
            X.shape[0] - non_zero,
            non_zero))
    else:
        X_str = X.astype(str)
        nans = ((X_str == "nan") | (X_str == "")).sum(axis=0) \
            if X.size else np.zeros(X.shape[1])
        return np.column_stack((
            np.tile(np.inf, X.shape[1]),
            np.tile(-np.inf, X.shape[1]),
            np.zeros(X.shape[1]),
            np.zeros(X.shape[1]),
            nans,
            X.shape[0] - nans))


def _nan_min_max(x, func, axis=0):
    if not sp.issparse(x):
        return func(x, axis=axis)
    if axis is None:
        extreme = func(x.data, axis=axis) if x.nnz else float('nan')
        if sparse_has_implicit_zeros(x):
            extreme = func([0, extreme])
        return extreme
    if axis == 0:
        x = x.T
    else:
        assert axis == 1

    # TODO check & transform to correct format
    r = []
    for row in x:
        values = row.data
        extreme = func(values) if values.size else float('nan')
        if sparse_has_implicit_zeros(row):
            extreme = func([0, extreme])
        r.append(extreme)
    return np.array(r)


def nanmin(x, axis=None):
    """ Equivalent of np.nammin that supports sparse or dense matrices. """
    return _nan_min_max(x, np.nanmin, axis)


def nanmax(x, axis=None):
    """ Equivalent of np.nammax that supports sparse or dense matrices. """
    return _nan_min_max(x, np.nanmax, axis)


def mean(x):
    """ Equivalent of np.mean that supports sparse or dense matrices. """
    m = (np.sum(x.data) / np.prod(x.shape)
         if sp.issparse(x) else
         np.mean(x))
    if np.isnan(m):
        warnings.warn('mean() resulted in nan. If input can contain nan values,'
                      ' perhaps you meant nanmean?', stacklevel=2)
    return m


def _apply_func(x, dense_func, sparse_func, axis=None):
    """ General wrapper for a function depending on sparse or dense matrices. """
    if not sp.issparse(x):
        return dense_func(x, axis=axis)
    if axis is None:
        return sparse_func(x)
    if axis in [0, 1]:
        arr = x if axis == 1 else x.T
        arr = arr.tocsr()
        return np.fromiter((sparse_func(row) for row in arr),
                           dtype=np.double, count=arr.shape[0])
    else:
        raise NotImplementedError


def nansum(x, axis=None):
    """ Equivalent of np.nansum that supports sparse or dense matrices. """
    def nansum_sparse(x):
        return np.nansum(x.data)

    return _apply_func(x, np.nansum, nansum_sparse, axis=axis)


def nanmean(x, axis=None):
    """ Equivalent of np.nanmean that supports sparse or dense matrices. """
    if not sp.issparse(x):
        means = np.nanmean(x, axis=axis)
    elif axis is None:
        means, _ = mean_variance_axis(x, axis=0)
        means = np.nanmean(means)
    else:
        means, _ = mean_variance_axis(x, axis=axis)

    return means


def nanvar(x, axis=None, ddof=0):
    """ Equivalent of np.nanvar that supports sparse or dense matrices. """
    def nanvar_sparse(x):
        n_vals = np.prod(x.shape) - np.sum(np.isnan(x.data))
        n_zeros = np.prod(x.shape) - len(x.data)
        mean = np.nansum(x.data) / n_vals
        return (np.nansum((x.data - mean) ** 2) + mean ** 2 * n_zeros) / (n_vals - ddof)

    return _apply_func(x, np.nanvar, nanvar_sparse, axis=axis)


def nanstd(x, axis=None, ddof=0):
    """ Equivalent of np.nanstd that supports sparse and dense matrices. """
    return np.sqrt(nanvar(x, axis=axis, ddof=ddof))


def nanmedian(x, axis=None):
    """ Equivalent of np.nanmedian that supports sparse or dense matrices. """
    def nanmedian_sparse(x):
        nz = np.logical_not(np.isnan(x.data))
        n_nan = sum(np.isnan(x.data))
        n_nonzero = sum(x.data[nz] != 0)
        n_zeros = np.prod(x.shape) - n_nonzero - n_nan
        if n_zeros > n_nonzero:
            # Typical case if use of sparse matrices make sense
            return 0
        else:
            # Possibly contains NaNs and
            # more nz values than zeros, so allocating memory should not be too problematic
            return np.nanmedian(x.toarray())

    return _apply_func(x, np.nanmedian, nanmedian_sparse, axis=axis)


def nanmode(x, axis=0):
    """ A temporary replacement for a scipy.stats.mode.

    This function returns mode NaN if all values are NaN (scipy<1.2.0 wrongly
    returns zero). Also, this function returns count NaN if all values are NaN
    (scipy=1.3.0 returns some number)."""
    nans = np.isnan(np.array(x)).sum(axis=axis, keepdims=True) == x.shape[axis]
    res = scipy.stats.stats.mode(x, axis)
    return scipy.stats.stats.ModeResult(np.where(nans, np.nan, res.mode),
                                        np.where(nans, np.nan, res.count))


def unique(x, return_counts=False):
    """ Equivalent of np.unique that supports sparse or dense matrices. """
    if not sp.issparse(x):
        return np.unique(x, return_counts=return_counts)

    implicit_zeros = sparse_count_implicit_zeros(x)
    explicit_zeros = not np.all(x.data)
    r = np.unique(x.data, return_counts=return_counts)
    if not implicit_zeros:
        return r

    if return_counts:
        zero_index = np.searchsorted(r[0], 0)
        if explicit_zeros:
            r[1][r[0] == 0.] += implicit_zeros
            return r
        return np.insert(r[0], zero_index, 0), np.insert(r[1], zero_index, implicit_zeros)
    else:
        if explicit_zeros:
            return r
        zero_index = np.searchsorted(r, 0)
        return np.insert(r, zero_index, 0)


def nanunique(*args, **kwargs):
    """ Return unique values while disregarding missing (np.nan) values.
    Supports sparse or dense matrices. """
    result = unique(*args, **kwargs)

    if isinstance(result, tuple):
        result, counts = result
        non_nan_mask = ~np.isnan(result)
        return result[non_nan_mask], counts[non_nan_mask]

    return result[~np.isnan(result)]


def digitize(x, bins, right=False):
    """Equivalent of np.digitize that supports sparse and dense matrices.

    If a sparse matrix is provided and the '0's belong to the '0'th bin, then
    a sparse matrix is returned.

    Because this can return both sparse and dense matrices, we must keep the
    return shape consistent. Since sparse matrices don't support 1d matrices,
    we reshape any returned 1d numpy array to a 2d matrix, with the first
    dimension shape being 1. This is equivalent to the behaviour of sparse
    matrices.

    Parameters
    ----------
    x : Union[np.ndarry, sp.csr_matrix, sp.csc_matrix]
    bins : np.ndarray
    right : Optional[bool]

    Returns
    -------
    Union[np.ndarray, sp.csr_matrix]

    """
    if not sp.issparse(x):
        # TODO Remove reshaping logic when support for numpy==1.9 is dropped
        original_shape = x.shape
        x = x.flatten()
        result = np.digitize(x, bins, right)
        result = result.reshape(original_shape)
        # In order to keep the return shape consistent, and sparse matrices
        # don't support 1d matrices, make sure to convert 1d to 2d matrices
        if result.ndim == 1:
            result = result.reshape(((1,) + result.shape))
        return result

    # Find the bin where zeros belong, depending on the `right` parameter
    zero_bin = np.searchsorted(bins, 0, side=['right', 'left'][right])

    if zero_bin == 0:
        r = sp.lil_matrix(x.shape, dtype=np.int64)
    else:
        r = zero_bin * np.ones(x.shape, dtype=np.int64)

    for idx, row in enumerate(x.tocsr()):
        # TODO Remove this check when support for numpy==1.9 is dropped
        if row.nnz > 0:
            r[idx, row.indices] = np.digitize(row.data, bins, right)

    # Orange mainly deals with `csr_matrix`, but `lil_matrix` is more efficient
    # for incremental building
    if sp.issparse(r):
        r = r.tocsr()

    return r


def var(x, axis=None, ddof=0):
    """ Equivalent of np.var that supports sparse and dense matrices. """
    if not sp.issparse(x):
        return np.var(x, axis, ddof=ddof)

    result = x.multiply(x).mean(axis) - np.square(x.mean(axis))
    result = np.squeeze(np.asarray(result))

    # Apply correction for degrees of freedom
    n = np.prod(x.shape) if axis is None else x.shape[axis]
    result *= n / (n - ddof)

    return result


def std(x, axis=None, ddof=0):
    """ Equivalent of np.std that supports sparse and dense matrices. """
    return np.sqrt(var(x, axis=axis, ddof=ddof))


def FDR(p_values: Iterable, dependent=False, m=None, ordered=False) -> Iterable:
    """ `False Discovery Rate <http://en.wikipedia.org/wiki/False_discovery_rate>`_
        correction on a list of p-values.

    :param p_values: list or np.ndarray of p-values.
    :param dependent: use correction for dependent hypotheses (default False).
    :param m: number of hypotheses tested (default ``len(p_values)``).
    :param ordered: prevent sorting of p-values if they are already sorted
        (default False).
    :return: list or np.ndarray, same as the input
    """
    if p_values is None or len(p_values) == 0 or \
            (m is not None and m <= 0):
        return None

    is_list = isinstance(p_values, list)
    p_values = np.array(p_values)
    if m is None:
        m = len(p_values)
    if not ordered:
        ordered = (np.diff(p_values) >= 0).all()
        if not ordered:
            indices = np.argsort(p_values)
            p_values = p_values[indices]

    if dependent:  # correct q for dependent tests
        m *= sum(1 / np.arange(1, m + 1))

    fdrs = (p_values * m / np.arange(1, len(p_values) + 1))[::-1]
    fdrs = np.array(np.minimum.accumulate(fdrs)[::-1])
    if not ordered:
        fdrs[indices] = fdrs.copy()
    return fdrs if not is_list else list(fdrs)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** `bincount` Raises ValueError for Object Arrays Containing NaNs

**Description:**
When using the `bincount` function with object arrays that include `NaN` values, a `ValueError` is thrown. This error occurs because the function attempts to convert `NaN` values to integers, which is not possible. As a result, counting occurrences in such arrays fails unexpectedly.

**Example Code:**
```python
import numpy as np
from Orange.statistics.util import bincount

x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)
result = bincount(x)
print(result[1])  # Expected to count the number of NaNs
```

**Expected Behavior:**
The `bincount` function should correctly handle object arrays containing `NaN` values by counting the non-NaN integers and separately tracking the number of `NaN` occurrences without raising an error.

**Actual Behavior:**
A `ValueError` is raised with the message: `cannot convert float NaN to integer`, preventing the function from completing the count.

[/ISSUE]
{
    "TestUtil.test_FDR": "PASSED",
    "TestUtil.test_FDR_dependent": "PASSED",
    "TestUtil.test_FDR_list": "PASSED",
    "TestUtil.test_FDR_m": "PASSED",
    "TestUtil.test_FDR_no_values": "PASSED",
    "TestUtil.test_array_equal_deprecated": "PASSED",
    "TestUtil.test_contingency": "PASSED",
    "TestUtil.test_mean": "PASSED",
    "TestUtil.test_nanmedian": "PASSED",
    "TestUtil.test_nanmedian_more_nonzeros": "PASSED",
    "TestUtil.test_nanmin_nanmax": "PASSED",
    "TestUtil.test_nanmode": "PASSED",
    "TestUtil.test_nanstd": "PASSED",
    "TestUtil.test_nanstd_with_ddof": "PASSED",
    "TestUtil.test_nansum": "PASSED",
    "TestUtil.test_nanvar": "PASSED",
    "TestUtil.test_nanvar_with_ddof": "PASSED",
    "TestUtil.test_stats": "PASSED",
    "TestUtil.test_stats_non_numeric": "PASSED",
    "TestUtil.test_stats_sparse": "PASSED",
    "TestUtil.test_stats_weights": "PASSED",
    "TestUtil.test_stats_weights_sparse": "PASSED",
    "TestUtil.test_std": "PASSED",
    "TestUtil.test_std_with_ddof": "PASSED",
    "TestUtil.test_var": "PASSED",
    "TestUtil.test_var_with_ddof": "PASSED",
    "TestUtil.test_weighted_contingency": "PASSED",
    "TestNanmean.test_axis_0": "PASSED",
    "TestNanmean.test_axis_1": "PASSED",
    "TestNanmean.test_axis_none": "PASSED",
    "TestDigitize.test_digitize": "PASSED",
    "TestDigitize.test_digitize_1d_array": "PASSED",
    "TestDigitize.test_digitize_right": "PASSED",
    "TestDigitize.test_digitize_sparse_zeroth_bin": "PASSED",
    "TestCountnans.test_1d_array": "PASSED",
    "TestCountnans.test_1d_array_with_axis_0": "PASSED",
    "TestCountnans.test_1d_array_with_axis_1_raises_exception": "PASSED",
    "TestCountnans.test_1d_weights_with_axis_0": "PASSED",
    "TestCountnans.test_1d_weights_with_axis_1": "PASSED",
    "TestCountnans.test_2d_matrix": "PASSED",
    "TestCountnans.test_2d_weights": "PASSED",
    "TestCountnans.test_dtype": "PASSED",
    "TestCountnans.test_on_columns": "PASSED",
    "TestCountnans.test_on_rows": "PASSED",
    "TestCountnans.test_shape_matches_dense_and_sparse": "PASSED",
    "TestCountnans.test_shape_matches_dense_and_sparse_with_axis_0": "PASSED",
    "TestCountnans.test_shape_matches_dense_and_sparse_with_axis_1": "PASSED",
    "TestBincount.test_adds_empty_bins": "PASSED",
    "TestBincount.test_all_nans": "PASSED",
    "TestBincount.test_all_zeros_or_nans": "PASSED",
    "TestBincount.test_count_nans": "PASSED",
    "TestBincount.test_count_nans_objectarray": "PASSED",
    "TestBincount.test_maxval_adds_empty_bins": "PASSED",
    "TestBincount.test_maxval_doesnt_truncate_values_when_too_small": "PASSED",
    "TestBincount.test_minlength_adds_empty_bins": "PASSED",
    "TestBincount.test_weights": "PASSED",
    "TestBincount.test_weights_with_nans": "PASSED",
    "TestBincount.test_weights_with_transposed_x": "PASSED",
    "TestUnique.test_nanunique_ignores_nans_in_counts": "PASSED",
    "TestUnique.test_nanunique_ignores_nans_in_values": "PASSED",
    "TestUnique.test_returns_counts": "PASSED",
    "TestUnique.test_returns_unique_values": "PASSED",
    "TestUnique.test_sparse_explicit_zeros": "PASSED"
}
diff --git a/Orange/statistics/util.py b/Orange/statistics/util.py
index a57156455..a4c2bcc32 100644
--- a/Orange/statistics/util.py
+++ b/Orange/statistics/util.py
@@ -82,7 +82,7 @@ def sparse_implicit_zero_weights(x, weights):
 def bincount(x, weights=None, max_val=None, minlength=0):
     """Return counts of values in array X.
 
-    Works kind of like np.bincount(), except that it also supports floating
+    Works kind of like np.bincount(), except that it also supports
     arrays with nans.
 
     Parameters
@@ -132,8 +132,8 @@ def bincount(x, weights=None, max_val=None, minlength=0):
 
         x = x.data
 
-    x = np.asanyarray(x)
-    if x.dtype.kind == 'f' and bn.anynan(x):
+    x = np.asanyarray(x, dtype=float)
+    if bn.anynan(x):
         nonnan = ~np.isnan(x)
         x = x[nonnan]
         if weights is not None:

{"Orange/statistics/util.py": "\"\"\"\nThis module provides alternatives for the few additional functions found in\nand once used from the bottlechest package (fork of bottleneck).\n\nIt also patches bottleneck to contain these functions.\n\"\"\"\nimport warnings\nfrom typing import Iterable\n\nimport bottleneck as bn\nimport numpy as np\nimport scipy.stats.stats\nfrom scipy import sparse as sp\n\nfrom sklearn.utils.sparsefuncs import mean_variance_axis\n\nfrom Orange.data.util import array_equal\nfrom Orange.util import deprecated\n\n# For backwards compatibility\narray_equal = deprecated(\"Orange.data.util.array_equal\")(array_equal)\n\n\ndef _count_nans_per_row_sparse(X, weights, dtype=None):\n    \"\"\" Count the number of nans (undefined) values per row. \"\"\"\n    if weights is not None:\n        X = X.tocoo(copy=False)\n        nonzero_mask = np.isnan(X.data)\n        nan_rows, nan_cols = X.row[nonzero_mask], X.col[nonzero_mask]\n\n        if weights.ndim == 1:\n            data_weights = weights[nan_rows]\n        else:\n            data_weights = weights[nan_rows, nan_cols]\n\n        w = sp.coo_matrix((data_weights, (nan_rows, nan_cols)), shape=X.shape)\n        w = w.tocsr()\n        return np.asarray(w.sum(axis=1), dtype=dtype).ravel()\n\n    if isinstance(X, (sp.csr_matrix, sp.csc_matrix)):\n        X = type(X)((np.isnan(X.data), X.indices, X.indptr), X.shape)\n        return np.asarray(X.sum(axis=1), dtype=dtype).ravel()\n    else:  # pragma: no cover\n        raise TypeError(\"unsupported type '{}'\".format(type(X).__name__))\n\n\ndef sparse_count_implicit_zeros(x):\n    \"\"\" Count the number of implicit zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) - x.nnz\n\n\ndef sparse_has_implicit_zeros(x):\n    \"\"\" Check if sparse matrix contains any implicit zeros. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n    return np.prod(x.shape) != x.nnz\n\n\ndef sparse_implicit_zero_weights(x, weights):\n    \"\"\" Extract the weight values of all zeros in a sparse matrix. \"\"\"\n    if not sp.issparse(x):\n        raise TypeError('The matrix provided was not sparse.')\n\n    if weights.ndim == 1:\n        # Match weights and x axis so `indices` will be set appropriately\n        if x.shape[0] == weights.shape[0]:\n            x = x.tocsc()\n        elif x.shape[1] == weights.shape[0]:\n            x = x.tocsr()\n        n_items = np.prod(x.shape)\n        zero_indices = np.setdiff1d(np.arange(n_items), x.indices, assume_unique=True)\n        return weights[zero_indices]\n    else:\n        # Can easily be implemented using a coo_matrix\n        raise NotImplementedError(\n            'Computing zero weights on ndimensinal weight matrix is not implemented'\n        )\n\n\ndef bincount(x, weights=None, max_val=None, minlength=0):\n    \"\"\"Return counts of values in array X.\n\n    Works kind of like np.bincount(), except that it also supports floating\n    arrays with nans.\n\n    Parameters\n    ----------\n    x : array_like, 1 dimension, nonnegative ints\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same shape as x.\n    max_val : int, optional\n        Indicates the maximum value we expect to find in X and sets the result\n        array size accordingly. E.g. if we set `max_val=2` yet the largest\n        value in X is 1, the result will contain a bin for the value 2, and\n        will be set to 0. See examples for usage.\n    minlength : int, optional\n        A minimum number of bins for the output array. See numpy docs for info.\n\n    Returns\n    -------\n    Tuple[np.ndarray, int]\n        Returns the bincounts and the number of NaN values.\n\n    Examples\n    --------\n    In case `max_val` is provided, the return shape includes bins for these\n    values as well, even if they do not appear in the data. However, this will\n    not truncate the bincount if values larger than `max_count` are found.\n    >>> bincount([0, 0, 1, 1, 2], max_val=4)\n    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)\n    >>> bincount([0, 1, 2, 3, 4], max_val=2)\n    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)\n\n    \"\"\"\n    # Store the original matrix before any manipulation to check for sparse\n    x_original = x\n    if sp.issparse(x):\n        if weights is not None:\n            # Match weights and x axis so `indices` will be set appropriately\n            if x.shape[0] == weights.shape[0]:\n                x = x.tocsc()\n            elif x.shape[1] == weights.shape[0]:\n                x = x.tocsr()\n\n            zero_weights = sparse_implicit_zero_weights(x, weights).sum()\n            weights = weights[x.indices]\n        else:\n            zero_weights = sparse_count_implicit_zeros(x)\n\n        x = x.data\n\n    x = np.asanyarray(x)\n    if x.dtype.kind == 'f' and bn.anynan(x):\n        nonnan = ~np.isnan(x)\n        x = x[nonnan]\n        if weights is not None:\n            nans = (~nonnan * weights).sum(axis=0)\n            weights = weights[nonnan]\n        else:\n            nans = (~nonnan).sum(axis=0)\n    else:\n        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)\n\n    if minlength == 0 and max_val is not None:\n        minlength = max_val + 1\n\n    bc = np.bincount(\n        x.astype(np.int32, copy=False), weights=weights, minlength=minlength\n    ).astype(float)\n    # Since `csr_matrix.values` only contain non-zero values or explicit\n    # zeros, we must count implicit zeros separately and add them to the\n    # explicit ones found before\n    if sp.issparse(x_original):\n        # If x contains only NaNs, then bc will be an empty array\n        if zero_weights and bc.size == 0:\n            bc = [zero_weights]\n        elif zero_weights:\n            bc[0] += zero_weights\n\n    return bc, nans\n\n\ndef countnans(x, weights=None, axis=None, dtype=None, keepdims=False):\n    \"\"\"\n    Count the undefined elements in an array along given axis.\n\n    Parameters\n    ----------\n    x : array_like\n    weights : array_like, optional\n        Weights to weight the nans with, before or after counting (depending\n        on the weights shape).\n    axis : int, optional\n    dtype : dtype, optional\n        The data type of the returned array.\n\n    Returns\n    -------\n    Union[np.ndarray, float]\n\n    \"\"\"\n    if not sp.issparse(x):\n        x = np.asanyarray(x)\n        isnan = np.isnan(x)\n        if weights is not None and weights.shape == x.shape:\n            isnan = isnan * weights\n\n        counts = isnan.sum(axis=axis, dtype=dtype, keepdims=keepdims)\n        if weights is not None and weights.shape != x.shape:\n            counts = counts * weights\n    else:\n        assert axis in [None, 0, 1], 'Only axis 0 and 1 are currently supported'\n        # To have consistent behaviour with dense matrices, raise error when\n        # `axis=1` and the array is 1d (e.g. [[1 2 3]])\n        if x.shape[0] == 1 and axis == 1:\n            raise ValueError('Axis %d is out of bounds' % axis)\n\n        arr = x if axis == 1 else x.T\n\n        if weights is not None:\n            weights = weights if axis == 1 else weights.T\n\n        arr = arr.tocsr()\n        counts = _count_nans_per_row_sparse(arr, weights, dtype=dtype)\n\n        # We want a scalar value if `axis=None` or if the sparse matrix is\n        # actually a vector (e.g. [[1 2 3]]), but has `ndim=2` due to scipy\n        # implementation\n        if axis is None or x.shape[0] == 1:\n            counts = counts.sum(dtype=dtype)\n\n    return counts\n\n\ndef contingency(X, y, max_X=None, max_y=None, weights=None, mask=None):\n    \"\"\"\n    Compute the contingency matrices for each column of X (excluding the masked)\n    versus the vector y.\n\n    If the array is 1-dimensional, a 2d contingency matrix is returned. If the\n    array is 2d, the function returns a 3d array, with the first dimension\n    corresponding to column index (variable in the input array).\n\n    The rows of contingency matrix correspond to values of variables, the\n    columns correspond to values in vector `y`.\n    (??? isn't it the other way around ???)\n\n    Rows in the input array can be weighted (argument `weights`). A subset of\n    columns can be selected by additional argument `mask`.\n\n    The function also returns a count of NaN values per each value of `y`.\n\n    Parameters\n    ----------\n    X : array_like\n        With values in columns.\n    y : 1d array\n        Vector of true values.\n    max_X : int\n        The maximal value in the array\n    max_y : int\n        The maximal value in `y`\n    weights : array_like\n        Row weights. When not None, contingencies contain weighted counts\n    mask : sequence\n        Discrete columns of X.\n\n    Returns\n    -------\n    contingencies: (m \u00d7 ny \u00d7 nx) array\n        m number of masked (used) columns (all if mask=None), i.e.\n        for each column of X;\n        ny number of uniques in y,\n        nx number of uniques in column of X.\n    nans : array_like\n        Number of nans in each column of X for each unique value of y.\n    \"\"\"\n    was_1d = False\n    if X.ndim == 1:\n        X = X[..., np.newaxis]\n        was_1d = True\n\n    contingencies, nans = [], []\n    ny = np.unique(y).size if max_y is None else max_y + 1\n    for i in range(X.shape[1]):\n        if mask is not None and not mask[i]:\n            contingencies.append(np.zeros((ny, max_X + 1)))\n            nans.append(np.zeros(ny))\n            continue\n        col = X[..., i]\n        nx = np.unique(col[~np.isnan(col)]).size if max_X is None else max_X + 1\n        if sp.issparse(col):\n            col = np.ravel(col.todense())\n        contingencies.append(\n            bincount(y + ny * col,\n                     minlength=ny * nx,\n                     weights=weights)[0].reshape(nx, ny).T)\n        nans.append(\n            bincount(y[np.isnan(col)], minlength=ny)[0])\n    if was_1d:\n        return contingencies[0], nans[0]\n    return np.array(contingencies), np.array(nans)\n\n\ndef stats(X, weights=None, compute_variance=False):\n    \"\"\"\n    Compute min, max, #nans, mean and variance.\n\n    Result is a tuple (min, max, mean, variance, #nans, #non-nans) or an\n    array of shape (len(X), 6).\n\n    The mean and the number of nans and non-nans are weighted.\n\n    Computation of variance requires an additional pass and is not enabled\n    by default. Zeros are filled in instead of variance.\n\n    Parameters\n    ----------\n    X : array_like, 1 or 2 dimensions\n        Input array.\n    weights : array_like, optional\n        Weights, array of the same length as `x`.\n    compute_variance : bool, optional\n        If set to True, the function also computes variance.\n\n    Returns\n    -------\n    out : a 6-element tuple or an array of shape (len(x), 6)\n        Computed (min, max, mean, variance or 0, #nans, #non-nans)\n\n    Raises\n    ------\n    ValueError\n        If the length of the weight vector does not match the length of the\n        array\n    \"\"\"\n    is_numeric = np.issubdtype(X.dtype, np.number)\n    is_sparse = sp.issparse(X)\n    weighted = weights is not None and X.dtype != object\n\n    def weighted_mean():\n        if is_sparse:\n            w_X = X.multiply(sp.csr_matrix(np.c_[weights] / sum(weights)))\n            return np.asarray(w_X.sum(axis=0)).ravel()\n        else:\n            return np.nansum(X * np.c_[weights] / sum(weights), axis=0)\n\n    if X.size and is_numeric and not is_sparse:\n        nans = np.isnan(X).sum(axis=0)\n        return np.column_stack((\n            np.nanmin(X, axis=0),\n            np.nanmax(X, axis=0),\n            np.nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.nanvar(X, axis=0) if compute_variance else np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n    elif is_sparse and X.size:\n        if compute_variance:\n            raise NotImplementedError\n\n        non_zero = np.bincount(X.nonzero()[1], minlength=X.shape[1])\n        X = X.tocsc()\n        return np.column_stack((\n            nanmin(X, axis=0),\n            nanmax(X, axis=0),\n            nanmean(X, axis=0) if not weighted else weighted_mean(),\n            np.zeros(X.shape[1]),      # variance not supported\n            X.shape[0] - non_zero,\n            non_zero))\n    else:\n        X_str = X.astype(str)\n        nans = ((X_str == \"nan\") | (X_str == \"\")).sum(axis=0) \\\n            if X.size else np.zeros(X.shape[1])\n        return np.column_stack((\n            np.tile(np.inf, X.shape[1]),\n            np.tile(-np.inf, X.shape[1]),\n            np.zeros(X.shape[1]),\n            np.zeros(X.shape[1]),\n            nans,\n            X.shape[0] - nans))\n\n\ndef _nan_min_max(x, func, axis=0):\n    if not sp.issparse(x):\n        return func(x, axis=axis)\n    if axis is None:\n        extreme = func(x.data, axis=axis) if x.nnz else float('nan')\n        if sparse_has_implicit_zeros(x):\n            extreme = func([0, extreme])\n        return extreme\n    if axis == 0:\n        x = x.T\n    else:\n        assert axis == 1\n\n    # TODO check & transform to correct format\n    r = []\n    for row in x:\n        values = row.data\n        extreme = func(values) if values.size else float('nan')\n        if sparse_has_implicit_zeros(row):\n            extreme = func([0, extreme])\n        r.append(extreme)\n    return np.array(r)\n\n\ndef nanmin(x, axis=None):\n    \"\"\" Equivalent of np.nammin that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmin, axis)\n\n\ndef nanmax(x, axis=None):\n    \"\"\" Equivalent of np.nammax that supports sparse or dense matrices. \"\"\"\n    return _nan_min_max(x, np.nanmax, axis)\n\n\ndef mean(x):\n    \"\"\" Equivalent of np.mean that supports sparse or dense matrices. \"\"\"\n    m = (np.sum(x.data) / np.prod(x.shape)\n         if sp.issparse(x) else\n         np.mean(x))\n    if np.isnan(m):\n        warnings.warn('mean() resulted in nan. If input can contain nan values,'\n                      ' perhaps you meant nanmean?', stacklevel=2)\n    return m\n\n\ndef _apply_func(x, dense_func, sparse_func, axis=None):\n    \"\"\" General wrapper for a function depending on sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return dense_func(x, axis=axis)\n    if axis is None:\n        return sparse_func(x)\n    if axis in [0, 1]:\n        arr = x if axis == 1 else x.T\n        arr = arr.tocsr()\n        return np.fromiter((sparse_func(row) for row in arr),\n                           dtype=np.double, count=arr.shape[0])\n    else:\n        raise NotImplementedError\n\n\ndef nansum(x, axis=None):\n    \"\"\" Equivalent of np.nansum that supports sparse or dense matrices. \"\"\"\n    def nansum_sparse(x):\n        return np.nansum(x.data)\n\n    return _apply_func(x, np.nansum, nansum_sparse, axis=axis)\n\n\ndef nanmean(x, axis=None):\n    \"\"\" Equivalent of np.nanmean that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        means = np.nanmean(x, axis=axis)\n    elif axis is None:\n        means, _ = mean_variance_axis(x, axis=0)\n        means = np.nanmean(means)\n    else:\n        means, _ = mean_variance_axis(x, axis=axis)\n\n    return means\n\n\ndef nanvar(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanvar that supports sparse or dense matrices. \"\"\"\n    def nanvar_sparse(x):\n        n_vals = np.prod(x.shape) - np.sum(np.isnan(x.data))\n        n_zeros = np.prod(x.shape) - len(x.data)\n        mean = np.nansum(x.data) / n_vals\n        return (np.nansum((x.data - mean) ** 2) + mean ** 2 * n_zeros) / (n_vals - ddof)\n\n    return _apply_func(x, np.nanvar, nanvar_sparse, axis=axis)\n\n\ndef nanstd(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.nanstd that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(nanvar(x, axis=axis, ddof=ddof))\n\n\ndef nanmedian(x, axis=None):\n    \"\"\" Equivalent of np.nanmedian that supports sparse or dense matrices. \"\"\"\n    def nanmedian_sparse(x):\n        nz = np.logical_not(np.isnan(x.data))\n        n_nan = sum(np.isnan(x.data))\n        n_nonzero = sum(x.data[nz] != 0)\n        n_zeros = np.prod(x.shape) - n_nonzero - n_nan\n        if n_zeros > n_nonzero:\n            # Typical case if use of sparse matrices make sense\n            return 0\n        else:\n            # Possibly contains NaNs and\n            # more nz values than zeros, so allocating memory should not be too problematic\n            return np.nanmedian(x.toarray())\n\n    return _apply_func(x, np.nanmedian, nanmedian_sparse, axis=axis)\n\n\ndef nanmode(x, axis=0):\n    \"\"\" A temporary replacement for a scipy.stats.mode.\n\n    This function returns mode NaN if all values are NaN (scipy<1.2.0 wrongly\n    returns zero). Also, this function returns count NaN if all values are NaN\n    (scipy=1.3.0 returns some number).\"\"\"\n    nans = np.isnan(np.array(x)).sum(axis=axis, keepdims=True) == x.shape[axis]\n    res = scipy.stats.stats.mode(x, axis)\n    return scipy.stats.stats.ModeResult(np.where(nans, np.nan, res.mode),\n                                        np.where(nans, np.nan, res.count))\n\n\ndef unique(x, return_counts=False):\n    \"\"\" Equivalent of np.unique that supports sparse or dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.unique(x, return_counts=return_counts)\n\n    implicit_zeros = sparse_count_implicit_zeros(x)\n    explicit_zeros = not np.all(x.data)\n    r = np.unique(x.data, return_counts=return_counts)\n    if not implicit_zeros:\n        return r\n\n    if return_counts:\n        zero_index = np.searchsorted(r[0], 0)\n        if explicit_zeros:\n            r[1][r[0] == 0.] += implicit_zeros\n            return r\n        return np.insert(r[0], zero_index, 0), np.insert(r[1], zero_index, implicit_zeros)\n    else:\n        if explicit_zeros:\n            return r\n        zero_index = np.searchsorted(r, 0)\n        return np.insert(r, zero_index, 0)\n\n\ndef nanunique(*args, **kwargs):\n    \"\"\" Return unique values while disregarding missing (np.nan) values.\n    Supports sparse or dense matrices. \"\"\"\n    result = unique(*args, **kwargs)\n\n    if isinstance(result, tuple):\n        result, counts = result\n        non_nan_mask = ~np.isnan(result)\n        return result[non_nan_mask], counts[non_nan_mask]\n\n    return result[~np.isnan(result)]\n\n\ndef digitize(x, bins, right=False):\n    \"\"\"Equivalent of np.digitize that supports sparse and dense matrices.\n\n    If a sparse matrix is provided and the '0's belong to the '0'th bin, then\n    a sparse matrix is returned.\n\n    Because this can return both sparse and dense matrices, we must keep the\n    return shape consistent. Since sparse matrices don't support 1d matrices,\n    we reshape any returned 1d numpy array to a 2d matrix, with the first\n    dimension shape being 1. This is equivalent to the behaviour of sparse\n    matrices.\n\n    Parameters\n    ----------\n    x : Union[np.ndarry, sp.csr_matrix, sp.csc_matrix]\n    bins : np.ndarray\n    right : Optional[bool]\n\n    Returns\n    -------\n    Union[np.ndarray, sp.csr_matrix]\n\n    \"\"\"\n    if not sp.issparse(x):\n        # TODO Remove reshaping logic when support for numpy==1.9 is dropped\n        original_shape = x.shape\n        x = x.flatten()\n        result = np.digitize(x, bins, right)\n        result = result.reshape(original_shape)\n        # In order to keep the return shape consistent, and sparse matrices\n        # don't support 1d matrices, make sure to convert 1d to 2d matrices\n        if result.ndim == 1:\n            result = result.reshape(((1,) + result.shape))\n        return result\n\n    # Find the bin where zeros belong, depending on the `right` parameter\n    zero_bin = np.searchsorted(bins, 0, side=['right', 'left'][right])\n\n    if zero_bin == 0:\n        r = sp.lil_matrix(x.shape, dtype=np.int64)\n    else:\n        r = zero_bin * np.ones(x.shape, dtype=np.int64)\n\n    for idx, row in enumerate(x.tocsr()):\n        # TODO Remove this check when support for numpy==1.9 is dropped\n        if row.nnz > 0:\n            r[idx, row.indices] = np.digitize(row.data, bins, right)\n\n    # Orange mainly deals with `csr_matrix`, but `lil_matrix` is more efficient\n    # for incremental building\n    if sp.issparse(r):\n        r = r.tocsr()\n\n    return r\n\n\ndef var(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.var that supports sparse and dense matrices. \"\"\"\n    if not sp.issparse(x):\n        return np.var(x, axis, ddof=ddof)\n\n    result = x.multiply(x).mean(axis) - np.square(x.mean(axis))\n    result = np.squeeze(np.asarray(result))\n\n    # Apply correction for degrees of freedom\n    n = np.prod(x.shape) if axis is None else x.shape[axis]\n    result *= n / (n - ddof)\n\n    return result\n\n\ndef std(x, axis=None, ddof=0):\n    \"\"\" Equivalent of np.std that supports sparse and dense matrices. \"\"\"\n    return np.sqrt(var(x, axis=axis, ddof=ddof))\n\n\ndef FDR(p_values: Iterable, dependent=False, m=None, ordered=False) -> Iterable:\n    \"\"\" `False Discovery Rate <http://en.wikipedia.org/wiki/False_discovery_rate>`_\n        correction on a list of p-values.\n\n    :param p_values: list or np.ndarray of p-values.\n    :param dependent: use correction for dependent hypotheses (default False).\n    :param m: number of hypotheses tested (default ``len(p_values)``).\n    :param ordered: prevent sorting of p-values if they are already sorted\n        (default False).\n    :return: list or np.ndarray, same as the input\n    \"\"\"\n    if p_values is None or len(p_values) == 0 or \\\n            (m is not None and m <= 0):\n        return None\n\n    is_list = isinstance(p_values, list)\n    p_values = np.array(p_values)\n    if m is None:\n        m = len(p_values)\n    if not ordered:\n        ordered = (np.diff(p_values) >= 0).all()\n        if not ordered:\n            indices = np.argsort(p_values)\n            p_values = p_values[indices]\n\n    if dependent:  # correct q for dependent tests\n        m *= sum(1 / np.arange(1, m + 1))\n\n    fdrs = (p_values * m / np.arange(1, len(p_values) + 1))[::-1]\n    fdrs = np.array(np.minimum.accumulate(fdrs)[::-1])\n    if not ordered:\n        fdrs[indices] = fdrs.copy()\n    return fdrs if not is_list else list(fdrs)\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `bincount` Raises ValueError for Object Arrays Containing NaNs

**Description:**
When using the `bincount` function with object arrays that include `NaN` values, a `ValueError` is thrown. This error occurs because the function attempts to convert `NaN` values to integers, which is not possible. As a result, counting occurrences in such arrays fails unexpectedly.

**Example Code:**
```python
import numpy as np
from Orange.statistics.util import bincount

x = np.array([0, 0, 1, 2, np.nan, 2], dtype=object)
result = bincount(x)
print(result[1])  # Expected to count the number of NaNs
```

**Expected Behavior:**
The `bincount` function should correctly handle object arrays containing `NaN` values by counting the non-NaN integers and separately tracking the number of `NaN` occurrences without raising an error.

**Actual Behavior:**
A `ValueError` is raised with the message: `cannot convert float NaN to integer`, preventing the function from completing the count.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/statistics/util.py
"""
This module provides alternatives for the few additional functions found in
and once used from the bottlechest package (fork of bottleneck).

It also patches bottleneck to contain these functions.
"""
import warnings
from typing import Iterable

import bottleneck as bn
import numpy as np
import scipy.stats.stats
from scipy import sparse as sp

from sklearn.utils.sparsefuncs import mean_variance_axis

from Orange.data.util import array_equal
from Orange.util import deprecated

# For backwards compatibility
array_equal = deprecated("Orange.data.util.array_equal")(array_equal)


def _count_nans_per_row_sparse(X, weights, dtype=None):
    """ Count the number of nans (undefined) values per row. """
    if weights is not None:
        X = X.tocoo(copy=False)
        nonzero_mask = np.isnan(X.data)
        nan_rows, nan_cols = X.row[nonzero_mask], X.col[nonzero_mask]

        if weights.ndim == 1:
            data_weights = weights[nan_rows]
        else:
            data_weights = weights[nan_rows, nan_cols]

        w = sp.coo_matrix((data_weights, (nan_rows, nan_cols)), shape=X.shape)
        w = w.tocsr()
        return np.asarray(w.sum(axis=1), dtype=dtype).ravel()

    if isinstance(X, (sp.csr_matrix, sp.csc_matrix)):
        X = type(X)((np.isnan(X.data), X.indices, X.indptr), X.shape)
        return np.asarray(X.sum(axis=1), dtype=dtype).ravel()
    else:  # pragma: no cover
        raise TypeError("unsupported type '{}'".format(type(X).__name__))


def sparse_count_implicit_zeros(x):
    """ Count the number of implicit zeros in a sparse matrix. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')
    return np.prod(x.shape) - x.nnz


def sparse_has_implicit_zeros(x):
    """ Check if sparse matrix contains any implicit zeros. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')
    return np.prod(x.shape) != x.nnz


def sparse_implicit_zero_weights(x, weights):
    """ Extract the weight values of all zeros in a sparse matrix. """
    if not sp.issparse(x):
        raise TypeError('The matrix provided was not sparse.')

    if weights.ndim == 1:
        # Match weights and x axis so `indices` will be set appropriately
        if x.shape[0] == weights.shape[0]:
            x = x.tocsc()
        elif x.shape[1] == weights.shape[0]:
            x = x.tocsr()
        n_items = np.prod(x.shape)
        zero_indices = np.setdiff1d(np.arange(n_items), x.indices, assume_unique=True)
        return weights[zero_indices]
    else:
        # Can easily be implemented using a coo_matrix
        raise NotImplementedError(
            'Computing zero weights on ndimensinal weight matrix is not implemented'
        )


def bincount(x, weights=None, max_val=None, minlength=0):
    """Return counts of values in array X.

    Works kind of like np.bincount(), except that it also supports floating
    arrays with nans.

    Parameters
    ----------
    x : array_like, 1 dimension, nonnegative ints
        Input array.
    weights : array_like, optional
        Weights, array of the same shape as x.
    max_val : int, optional
        Indicates the maximum value we expect to find in X and sets the result
        array size accordingly. E.g. if we set `max_val=2` yet the largest
        value in X is 1, the result will contain a bin for the value 2, and
        will be set to 0. See examples for usage.
    minlength : int, optional
        A minimum number of bins for the output array. See numpy docs for info.

    Returns
    -------
    Tuple[np.ndarray, int]
        Returns the bincounts and the number of NaN values.

    Examples
    --------
    In case `max_val` is provided, the return shape includes bins for these
    values as well, even if they do not appear in the data. However, this will
    not truncate the bincount if values larger than `max_count` are found.
    >>> bincount([0, 0, 1, 1, 2], max_val=4)
    (array([ 2.,  2.,  1.,  0.,  0.]), 0.0)
    >>> bincount([0, 1, 2, 3, 4], max_val=2)
    (array([ 1.,  1.,  1.,  1.,  1.]), 0.0)

    """
    # Store the original matrix before any manipulation to check for sparse
    x_original = x
    if sp.issparse(x):
        if weights is not None:
            # Match weights and x axis so `indices` will be set appropriately
            if x.shape[0] == weights.shape[0]:
                x = x.tocsc()
            elif x.shape[1] == weights.shape[0]:
                x = x.tocsr()

            zero_weights = sparse_implicit_zero_weights(x, weights).sum()
            weights = weights[x.indices]
        else:
            zero_weights = sparse_count_implicit_zeros(x)

        x = x.data

    x = np.asanyarray(x)
    if x.dtype.kind == 'f' and bn.anynan(x):
        nonnan = ~np.isnan(x)
        x = x[nonnan]
        if weights is not None:
            nans = (~nonnan * weights).sum(axis=0)
            weights = weights[nonnan]
        else:
            nans = (~nonnan).sum(axis=0)
    else:
        nans = 0. if x.ndim == 1 else np.zeros(x.shape[1], dtype=float)

    if minlength == 0 and max_val is not None:
        minlength = max_val + 1

    bc = np.bincount(
        x.astype(np.int32, copy=False), weights=weights, minlength=minlength
    ).astype(float)
    # Since `csr_matrix.values` only contain non-zero values or explicit
    # zeros, we must count implicit zeros separately and add them to the
    # explicit ones found before
    if sp.issparse(x_original):
        # If x contains only NaNs, then bc will be an empty array
        if zero_weights and bc.size == 0:
            bc = [zero_weights]
        elif zero_weights:
            bc[0] += zero_weights

    return bc, nans


def countnans(x, weights=None, axis=None, dtype=None, keepdims=False):
    """
    Count the undefined elements in an array along given axis.

    Parameters
    ----------
    x : array_like
    weights : array_like, optional
        Weights to weight the nans with, before or after counting (depending
        on the weights shape).
    axis : int, optional
    dtype : dtype, optional
        The data type of the returned array.

    Returns
    -------
    Union[np.ndarray, float]

    """
    if not sp.issparse(x):
        x = np.asanyarray(x)
        isnan = np.isnan(x)
        if weights is not None and weights.shape == x.shape:
            isnan = isnan * weights

        counts = isnan.sum(axis=axis, dtype=dtype, keepdims=keepdims)
        if weights is not None and weights.shape != x.shape:
            counts = counts * weights
    else:
        assert axis in [None, 0, 1], 'Only axis 0 and 1 are currently supported'
        # To have consistent behaviour with dense matrices, raise error when
        # `axis=1` and the array is 1d (e.g. [[1 2 3]])
        if x.shape[0] == 1 and axis == 1:
            raise ValueError('Axis %d is out of bounds' % axis)

        arr = x if axis == 1 else x.T

        if weights is not None:
            weights = weights if axis == 1 else weights.T

        arr = arr.tocsr()
        counts = _count_nans_per_row_sparse(arr, weights, dtype=dtype)

        # We want a scalar value if `axis=None` or if the sparse matrix is
        # actually a vector (e.g. [[1 2 3]]), but has `ndim=2` due to scipy
        # implementation
        if axis is None or x.shape[0] == 1:
            counts = counts.sum(dtype=dtype)

    return counts


def contingency(X, y, max_X=None, max_y=None, weights=None, mask=None):
    """
    Compute the contingency matrices for each column of X (excluding the masked)
    versus the vector y.

    If the array is 1-dimensional, a 2d contingency matrix is returned. If the
    array is 2d, the function returns a 3d array, with the first dimension
    corresponding to column index (variable in the input array).

    The rows of contingency matrix correspond to values of variables, the
    columns correspond to values in vector `y`.
    (??? isn't it the other way around ???)

    Rows in the input array can be weighted (argument `weights`). A subset of
    columns can be selected by additional argument `mask`.

    The function also returns a count of NaN values per each value of `y`.

    Parameters
    ----------
    X : array_like
        With values in columns.
    y : 1d array
        Vector of true values.
    max_X : int
        The maximal value in the array
    max_y : int
        The maximal value in `y`
    weights : array_like
        Row weights. When not None, contingencies contain weighted counts
    mask : sequence
        Discrete columns of X.

    Returns
    -------
    contingencies: (m × ny × nx) array
        m number of masked (used) columns (all if mask=None), i.e.
        for each column of X;
        ny number of uniques in y,
        nx number of uniques in column of X.
    nans : array_like
        Number of nans in each column of X for each unique value of y.
    """
    was_1d = False
    if X.ndim == 1:
        X = X[..., np.newaxis]
        was_1d = True

    contingencies, nans = [], []
    ny = np.unique(y).size if max_y is None else max_y + 1
    for i in range(X.shape[1]):
        if mask is not None and not mask[i]:
            contingencies.append(np.zeros((ny, max_X + 1)))
            nans.append(np.zeros(ny))
            continue
        col = X[..., i]
        nx = np.unique(col[~np.isnan(col)]).size if max_X is None else max_X + 1
        if sp.issparse(col):
            col = np.ravel(col.todense())
        contingencies.append(
            bincount(y + ny * col,
                     minlength=ny * nx,
                     weights=weights)[0].reshape(nx, ny).T)
        nans.append(
            bincount(y[np.isnan(col)], minlength=ny)[0])
    if was_1d:
        return contingencies[0], nans[0]
    return np.array(contingencies), np.array(nans)


def stats(X, weights=None, compute_variance=False):
    """
    Compute min, max, #nans, mean and variance.

    Result is a tuple (min, max, mean, variance, #nans, #non-nans) or an
    array of shape (len(X), 6).

    The mean and the number of nans and non-nans are weighted.

    Computation of variance requires an additional pass and is not enabled
    by default. Zeros are filled in instead of variance.

    Parameters
    ----------
    X : array_like, 1 or 2 dimensions
        Input array.
    weights : array_like, optional
        Weights, array of the same length as `x`.
    compute_variance : bool, optional
        If set to True, the function also computes variance.

    Returns
    -------
    out : a 6-element tuple or an array of shape (len(x), 6)
        Computed (min, max, mean, variance or 0, #nans, #non-nans)

    Raises
    ------
    ValueError
        If the length of the weight vector does not match the length of the
        array
    """
    is_numeric = np.issubdtype(X.dtype, np.number)
    is_sparse = sp.issparse(X)
    weighted = weights is not None and X.dtype != object

    def weighted_mean():
        if is_sparse:
            w_X = X.multiply(sp.csr_matrix(np.c_[weights] / sum(weights)))
            return np.asarray(w_X.sum(axis=0)).ravel()
        else:
            return np.nansum(X * np.c_[weights] / sum(weights), axis=0)

    if X.size and is_numeric and not is_sparse:
        nans = np.isnan(X).sum(axis=0)
        return np.column_stack((
            np.nanmin(X, axis=0),
            np.nanmax(X, axis=0),
            np.nanmean(X, axis=0) if not weighted else weighted_mean(),
            np.nanvar(X, axis=0) if compute_variance else np.zeros(X.shape[1]),
            nans,
            X.shape[0] - nans))
    elif is_sparse and X.size:
        if compute_variance:
            raise NotImplementedError

        non_zero = np.bincount(X.nonzero()[1], minlength=X.shape[1])
        X = X.tocsc()
        return np.column_stack((
            nanmin(X, axis=0),
            nanmax(X, axis=0),
            nanmean(X, axis=0) if not weighted else weighted_mean(),
            np.zeros(X.shape[1]),      # variance not supported
            X.shape[0] - non_zero,
            non_zero))
    else:
        X_str = X.astype(str)
        nans = ((X_str == "nan") | (X_str == "")).sum(axis=0) \
            if X.size else np.zeros(X.shape[1])
        return np.column_stack((
            np.tile(np.inf, X.shape[1]),
            np.tile(-np.inf, X.shape[1]),
            np.zeros(X.shape[1]),
            np.zeros(X.shape[1]),
            nans,
            X.shape[0] - nans))


def _nan_min_max(x, func, axis=0):
    if not sp.issparse(x):
        return func(x, axis=axis)
    if axis is None:
        extreme = func(x.data, axis=axis) if x.nnz else float('nan')
        if sparse_has_implicit_zeros(x):
            extreme = func([0, extreme])
        return extreme
    if axis == 0:
        x = x.T
    else:
        assert axis == 1

    # TODO check & transform to correct format
    r = []
    for row in x:
        values = row.data
        extreme = func(values) if values.size else float('nan')
        if sparse_has_implicit_zeros(row):
            extreme = func([0, extreme])
        r.append(extreme)
    return np.array(r)


def nanmin(x, axis=None):
    """ Equivalent of np.nammin that supports sparse or dense matrices. """
    return _nan_min_max(x, np.nanmin, axis)


def nanmax(x, axis=None):
    """ Equivalent of np.nammax that supports sparse or dense matrices. """
    return _nan_min_max(x, np.nanmax, axis)


def mean(x):
    """ Equivalent of np.mean that supports sparse or dense matrices. """
    m = (np.sum(x.data) / np.prod(x.shape)
         if sp.issparse(x) else
         np.mean(x))
    if np.isnan(m):
        warnings.warn('mean() resulted in nan. If input can contain nan values,'
                      ' perhaps you meant nanmean?', stacklevel=2)
    return m


def _apply_func(x, dense_func, sparse_func, axis=None):
    """ General wrapper for a function depending on sparse or dense matrices. """
    if not sp.issparse(x):
        return dense_func(x, axis=axis)
    if axis is None:
        return sparse_func(x)
    if axis in [0, 1]:
        arr = x if axis == 1 else x.T
        arr = arr.tocsr()
        return np.fromiter((sparse_func(row) for row in arr),
                           dtype=np.double, count=arr.shape[0])
    else:
        raise NotImplementedError


def nansum(x, axis=None):
    """ Equivalent of np.nansum that supports sparse or dense matrices. """
    def nansum_sparse(x):
        return np.nansum(x.data)

    return _apply_func(x, np.nansum, nansum_sparse, axis=axis)


def nanmean(x, axis=None):
    """ Equivalent of np.nanmean that supports sparse or dense matrices. """
    if not sp.issparse(x):
        means = np.nanmean(x, axis=axis)
    elif axis is None:
        means, _ = mean_variance_axis(x, axis=0)
        means = np.nanmean(means)
    else:
        means, _ = mean_variance_axis(x, axis=axis)

    return means


def nanvar(x, axis=None, ddof=0):
    """ Equivalent of np.nanvar that supports sparse or dense matrices. """
    def nanvar_sparse(x):
        n_vals = np.prod(x.shape) - np.sum(np.isnan(x.data))
        n_zeros = np.prod(x.shape) - len(x.data)
        mean = np.nansum(x.data) / n_vals
        return (np.nansum((x.data - mean) ** 2) + mean ** 2 * n_zeros) / (n_vals - ddof)

    return _apply_func(x, np.nanvar, nanvar_sparse, axis=axis)


def nanstd(x, axis=None, ddof=0):
    """ Equivalent of np.nanstd that supports sparse and dense matrices. """
    return np.sqrt(nanvar(x, axis=axis, ddof=ddof))


def nanmedian(x, axis=None):
    """ Equivalent of np.nanmedian that supports sparse or dense matrices. """
    def nanmedian_sparse(x):
        nz = np.logical_not(np.isnan(x.data))
        n_nan = sum(np.isnan(x.data))
        n_nonzero = sum(x.data[nz] != 0)
        n_zeros = np.prod(x.shape) - n_nonzero - n_nan
        if n_zeros > n_nonzero:
            # Typical case if use of sparse matrices make sense
            return 0
        else:
            # Possibly contains NaNs and
            # more nz values than zeros, so allocating memory should not be too problematic
            return np.nanmedian(x.toarray())

    return _apply_func(x, np.nanmedian, nanmedian_sparse, axis=axis)


def nanmode(x, axis=0):
    """ A temporary replacement for a scipy.stats.mode.

    This function returns mode NaN if all values are NaN (scipy<1.2.0 wrongly
    returns zero). Also, this function returns count NaN if all values are NaN
    (scipy=1.3.0 returns some number)."""
    nans = np.isnan(np.array(x)).sum(axis=axis, keepdims=True) == x.shape[axis]
    res = scipy.stats.stats.mode(x, axis)
    return scipy.stats.stats.ModeResult(np.where(nans, np.nan, res.mode),
                                        np.where(nans, np.nan, res.count))


def unique(x, return_counts=False):
    """ Equivalent of np.unique that supports sparse or dense matrices. """
    if not sp.issparse(x):
        return np.unique(x, return_counts=return_counts)

    implicit_zeros = sparse_count_implicit_zeros(x)
    explicit_zeros = not np.all(x.data)
    r = np.unique(x.data, return_counts=return_counts)
    if not implicit_zeros:
        return r

    if return_counts:
        zero_index = np.searchsorted(r[0], 0)
        if explicit_zeros:
            r[1][r[0] == 0.] += implicit_zeros
            return r
        return np.insert(r[0], zero_index, 0), np.insert(r[1], zero_index, implicit_zeros)
    else:
        if explicit_zeros:
            return r
        zero_index = np.searchsorted(r, 0)
        return np.insert(r, zero_index, 0)


def nanunique(*args, **kwargs):
    """ Return unique values while disregarding missing (np.nan) values.
    Supports sparse or dense matrices. """
    result = unique(*args, **kwargs)

    if isinstance(result, tuple):
        result, counts = result
        non_nan_mask = ~np.isnan(result)
        return result[non_nan_mask], counts[non_nan_mask]

    return result[~np.isnan(result)]


def digitize(x, bins, right=False):
    """Equivalent of np.digitize that supports sparse and dense matrices.

    If a sparse matrix is provided and the '0's belong to the '0'th bin, then
    a sparse matrix is returned.

    Because this can return both sparse and dense matrices, we must keep the
    return shape consistent. Since sparse matrices don't support 1d matrices,
    we reshape any returned 1d numpy array to a 2d matrix, with the first
    dimension shape being 1. This is equivalent to the behaviour of sparse
    matrices.

    Parameters
    ----------
    x : Union[np.ndarry, sp.csr_matrix, sp.csc_matrix]
    bins : np.ndarray
    right : Optional[bool]

    Returns
    -------
    Union[np.ndarray, sp.csr_matrix]

    """
    if not sp.issparse(x):
        # TODO Remove reshaping logic when support for numpy==1.9 is dropped
        original_shape = x.shape
        x = x.flatten()
        result = np.digitize(x, bins, right)
        result = result.reshape(original_shape)
        # In order to keep the return shape consistent, and sparse matrices
        # don't support 1d matrices, make sure to convert 1d to 2d matrices
        if result.ndim == 1:
            result = result.reshape(((1,) + result.shape))
        return result

    # Find the bin where zeros belong, depending on the `right` parameter
    zero_bin = np.searchsorted(bins, 0, side=['right', 'left'][right])

    if zero_bin == 0:
        r = sp.lil_matrix(x.shape, dtype=np.int64)
    else:
        r = zero_bin * np.ones(x.shape, dtype=np.int64)

    for idx, row in enumerate(x.tocsr()):
        # TODO Remove this check when support for numpy==1.9 is dropped
        if row.nnz > 0:
            r[idx, row.indices] = np.digitize(row.data, bins, right)

    # Orange mainly deals with `csr_matrix`, but `lil_matrix` is more efficient
    # for incremental building
    if sp.issparse(r):
        r = r.tocsr()

    return r


def var(x, axis=None, ddof=0):
    """ Equivalent of np.var that supports sparse and dense matrices. """
    if not sp.issparse(x):
        return np.var(x, axis, ddof=ddof)

    result = x.multiply(x).mean(axis) - np.square(x.mean(axis))
    result = np.squeeze(np.asarray(result))

    # Apply correction for degrees of freedom
    n = np.prod(x.shape) if axis is None else x.shape[axis]
    result *= n / (n - ddof)

    return result


def std(x, axis=None, ddof=0):
    """ Equivalent of np.std that supports sparse and dense matrices. """
    return np.sqrt(var(x, axis=axis, ddof=ddof))


def FDR(p_values: Iterable, dependent=False, m=None, ordered=False) -> Iterable:
    """ `False Discovery Rate <http://en.wikipedia.org/wiki/False_discovery_rate>`_
        correction on a list of p-values.

    :param p_values: list or np.ndarray of p-values.
    :param dependent: use correction for dependent hypotheses (default False).
    :param m: number of hypotheses tested (default ``len(p_values)``).
    :param ordered: prevent sorting of p-values if they are already sorted
        (default False).
    :return: list or np.ndarray, same as the input
    """
    if p_values is None or len(p_values) == 0 or \
            (m is not None and m <= 0):
        return None

    is_list = isinstance(p_values, list)
    p_values = np.array(p_values)
    if m is None:
        m = len(p_values)
    if not ordered:
        ordered = (np.diff(p_values) >= 0).all()
        if not ordered:
            indices = np.argsort(p_values)
            p_values = p_values[indices]

    if dependent:  # correct q for dependent tests
        m *= sum(1 / np.arange(1, m + 1))

    fdrs = (p_values * m / np.arange(1, len(p_values) + 1))[::-1]
    fdrs = np.array(np.minimum.accumulate(fdrs)[::-1])
    if not ordered:
        fdrs[indices] = fdrs.copy()
    return fdrs if not is_list else list(fdrs)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user