From fe68e01393f2993110879cd452d77539d8c03de1 Mon Sep 17 00:00:00 2001 From: Slobodan Ilic Date: Tue, 15 Jan 2019 14:07:40 +0100 Subject: [PATCH 1/2] Update pre-commit configuration --- .flake8 | 29 +++++++++++++++++++++++++++++ .pre-commit-config.yaml | 8 +++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..da870221e --- /dev/null +++ b/.flake8 @@ -0,0 +1,29 @@ +# Recommended flake8 settings while editing crunch-cube, we use Black for the final linting/say in how code is formatted +# +# pip install flake8 flake8-bugbear +# +# This will warn/error on things that black does not fix, on purpose. + +[flake8] +# max line length is set to 88 in black, here it is set to 80 and we enable bugbear's B950 warning, which is: +# +# B950: Line too long. This is a pragmatic equivalent of pycodestyle’s E501: it +# considers “max-line-length” but only triggers when the value has been +# exceeded by more than 10%. You will no longer be forced to reformat code due +# to the closing parenthesis being one character too far to satisfy the linter. +# At the same time, if you do significantly violate the line length, you will +# receive a message that states what the actual limit is. This is inspired by +# Raymond Hettinger’s “Beyond PEP 8” talk and highway patrol not stopping you +# if you drive < 5mph too fast. Disable E501 to avoid duplicate warnings. +max-line-length = 80 +max-complexity = 12 +select = E,F,W,C,B,B9 +ignore = + # E123 closing bracket does not match indentation of opening bracket’s line + E123 + # E203 whitespace before ‘:’ (Not PEP8 compliant, Python Black) + E203 + # E501 line too long (82 > 79 characters) (replaced by B950 from flake8-bugbear, https://github.com/PyCQA/flake8-bugbear) + E501 + # W503 line break before binary operator (Not PEP8 compliant, Python Black) + W503 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 726aa2cd8..6363f0961 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,14 @@ repos: + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v1.4.0-1 hooks: - id: flake8 - id: end-of-file-fixer - id: trailing-whitespace - - id: autopep8-wrapper + +- repo: https://github.com/ambv/black + rev: stable + hooks: + - id: black + language_version: python3.6 From 085285bee1fb54bd9d52d989fa85c1e1f4285648 Mon Sep 17 00:00:00 2001 From: Slobodan Ilic Date: Tue, 15 Jan 2019 14:11:09 +0100 Subject: [PATCH 2/2] Blacken Crunch Cube --- docs/source/conf.py | 61 +- setup.py | 37 +- src/cr/__init__.py | 3 +- src/cr/cube/__init__.py | 2 +- src/cr/cube/crunch_cube.py | 369 ++-- src/cr/cube/cube_slice.py | 97 +- src/cr/cube/dimension.py | 184 +- src/cr/cube/enum.py | 22 +- src/cr/cube/measures/index.py | 18 +- src/cr/cube/measures/scale_means.py | 28 +- src/cr/cube/util.py | 21 +- tests/fixtures/__init__.py | 13 +- tests/integration/test_crunch_cube.py | 1805 +++++++++-------- tests/integration/test_cube_slice.py | 105 +- tests/integration/test_dimension.py | 345 ++-- .../integration/test_headers_and_subtotals.py | 1120 +++++----- tests/integration/test_index.py | 114 +- tests/integration/test_index_table.py | 279 ++- tests/integration/test_multiple_response.py | 1804 +++++++++++----- tests/integration/test_scale_means.py | 142 +- tests/integration/test_z_scores.py | 394 ++-- tests/unit/test_crunch_cube.py | 669 +++--- tests/unit/test_cube_slice.py | 318 +-- tests/unit/test_dimension.py | 691 ++++--- tests/unit/test_enum.py | 17 +- tests/unit/test_index_table.py | 30 +- tests/unit/test_scale_means.py | 92 +- tests/unit/test_util.py | 28 +- tests/unitutil.py | 15 +- 29 files changed, 5114 insertions(+), 3709 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ccd0be809..de9f6be95 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -31,41 +31,41 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', + "sphinx.ext.autodoc", + "sphinx.ext.doctest", # 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', + "sphinx.ext.todo", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", # 'sphinx.ext.githubpages' # 'sphinxcontrib.napoleon' ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'Crunch Cube' -copyright = u'2017, Crunch.io' -author = u'Crunch.io' +project = u"Crunch Cube" +copyright = u"2017, Crunch.io" +author = u"Crunch.io" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = u'1.0' +version = u"1.0" # The full version, including alpha/beta/rc tags. -release = u'1.0' +release = u"1.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -80,7 +80,7 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -91,9 +91,9 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'bizstyle' +html_theme = "bizstyle" -html_logo = '_static/crunch_logo.png' +html_logo = "_static/crunch_logo.png" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -104,7 +104,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -116,7 +116,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'CrunchCubedoc' +htmlhelp_basename = "CrunchCubedoc" # -- Options for LaTeX output --------------------------------------------- @@ -125,15 +125,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -143,8 +140,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'CrunchCube.tex', u'Crunch Cube Documentation', - u'Crunch.io', 'manual'), + (master_doc, "CrunchCube.tex", u"Crunch Cube Documentation", u"Crunch.io", "manual") ] @@ -152,10 +148,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'crunchcube', u'Crunch Cube Documentation', - [author], 1) -] +man_pages = [(master_doc, "crunchcube", u"Crunch Cube Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -164,11 +157,17 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'CrunchCube', u'Crunch Cube Documentation', - author, 'CrunchCube', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "CrunchCube", + u"Crunch Cube Documentation", + author, + "CrunchCube", + "One line description of project.", + "Miscellaneous", + ) ] # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {"https://docs.python.org/": None} diff --git a/setup.py b/setup.py index f7af44805..f188bac3b 100644 --- a/setup.py +++ b/setup.py @@ -21,49 +21,40 @@ def ascii_bytes_from(path, *paths): # read required text from files thisdir = os.path.dirname(__file__) -init_py = ascii_bytes_from(thisdir, 'src', 'cr', 'cube', '__init__.py') -readme = ascii_bytes_from(thisdir, 'README.md') +init_py = ascii_bytes_from(thisdir, "src", "cr", "cube", "__init__.py") +readme = ascii_bytes_from(thisdir, "README.md") # Read the version from cr.cube.__version__ without importing the package # (and thus attempting to import packages it depends on that may not be # installed yet). This allows users to check installed version with # `python -c 'from cr.cube import __version__; print(__version__)` -version = re.search("__version__ = '([^']+)'", init_py).group(1) +version = re.search('__version__ = "([^"]+)"', init_py).group(1) -install_requires = [ - 'scipy', - 'tabulate', -] +install_requires = ["scipy", "tabulate"] -test_requires = [ - 'pytest', - 'pytest-cov', - 'mock', -] +test_requires = ["pytest", "pytest-cov", "mock"] setup( - name='cr.cube', + name="cr.cube", version=version, description="Crunch.io Cube library", long_description=readme, long_description_content_type="text/markdown", - url='https://github.com/Crunch-io/crunch-cube/', + url="https://github.com/Crunch-io/crunch-cube/", classifiers=[ "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", ], - author='Crunch.io', - author_email='dev@crunch.io', - license='MIT License', + author="Crunch.io", + author_email="dev@crunch.io", + license="MIT License", install_requires=install_requires, tests_require=test_requires, - extras_require={ - 'testing': test_requires, - }, - packages=find_packages('src', exclude=['tests']), - package_dir={'': 'src'}, + extras_require={"testing": test_requires}, + packages=find_packages("src", exclude=["tests"]), + package_dir={"": "src"}, include_package_data=True, entry_points={}, - namespace_packages=['cr'], + namespace_packages=["cr"], zip_safe=True, ) diff --git a/src/cr/__init__.py b/src/cr/__init__.py index ed3a9e5e1..fe765ce27 100644 --- a/src/cr/__init__.py +++ b/src/cr/__init__.py @@ -1,6 +1,7 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages try: # pragma: no cover - __import__('pkg_resources').declare_namespace(__name__) + __import__("pkg_resources").declare_namespace(__name__) except ImportError: # pragma: no cover from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/cr/cube/__init__.py b/src/cr/cube/__init__.py index 4b34bb64d..49e036cd8 100644 --- a/src/cr/cube/__init__.py +++ b/src/cr/cube/__init__.py @@ -2,4 +2,4 @@ """Initialization module for crunch-cube package.""" -__version__ = '1.8.6' +__version__ = "1.8.6" diff --git a/src/cr/cube/crunch_cube.py b/src/cr/cube/crunch_cube.py index 84006c069..e677521d2 100644 --- a/src/cr/cube/crunch_cube.py +++ b/src/cr/cube/crunch_cube.py @@ -20,7 +20,7 @@ from cr.cube.measures.scale_means import ScaleMeans from cr.cube.util import lazyproperty -np.seterr(divide='ignore', invalid='ignore') +np.seterr(divide="ignore", invalid="ignore") class CrunchCube(object): @@ -69,16 +69,22 @@ def __repr__(self): instance variable values. """ try: - dimensionality = ' x '.join(dt.name for dt in self.dim_types) - return ( - "%s(name='%s', dim_types='%s')" % - (type(self).__name__, self.name, dimensionality) + dimensionality = " x ".join(dt.name for dt in self.dim_types) + return "%s(name='%s', dim_types='%s')" % ( + type(self).__name__, + self.name, + dimensionality, ) except Exception: return super(CrunchCube, self).__repr__() - def as_array(self, include_missing=False, weighted=True, - include_transforms_for_dims=None, prune=False): + def as_array( + self, + include_missing=False, + weighted=True, + include_transforms_for_dims=None, + prune=False, + ): """Return `ndarray` representing cube values. Returns the tabular representation of the crunch cube. The returned @@ -110,23 +116,18 @@ def as_array(self, include_missing=False, weighted=True, array = self._as_array( include_missing=include_missing, weighted=weighted, - include_transforms_for_dims=include_transforms_for_dims + include_transforms_for_dims=include_transforms_for_dims, ) # ---prune array if pruning was requested--- if prune: - array = self._prune_body( - array, transforms=include_transforms_for_dims - ) + array = self._prune_body(array, transforms=include_transforms_for_dims) return self._drop_mr_cat_dims(array) def count(self, weighted=True): """Return numberic count of rows considered for cube response.""" - return ( - self._measures.weighted_n if weighted - else self._measures.unweighted_n - ) + return self._measures.weighted_n if weighted else self._measures.unweighted_n @lazyproperty def description(self): @@ -156,7 +157,7 @@ def dimensions(self): @lazyproperty def filter_annotation(self): """Get cube's filter annotation.""" - return self._cube_dict.get('filter_names', []) + return self._cube_dict.get("filter_names", []) def get_slices(self, ca_as_0th=False): """Return list of :class:`.CubeSlice` objects. @@ -169,10 +170,7 @@ def get_slices(self, ca_as_0th=False): if self.ndim < 3 and not ca_as_0th: return [CubeSlice(self, 0)] - return [ - CubeSlice(self, i, ca_as_0th) - for i, _ in enumerate(self.labels()[0]) - ] + return [CubeSlice(self, i, ca_as_0th) for i, _ in enumerate(self.labels()[0])] @lazyproperty def has_means(self): @@ -191,7 +189,7 @@ def index(self, weighted=True, prune=False): """ warnings.warn( "CrunchCube.index() is deprecated. Use CubeSlice.index_table().", - DeprecationWarning + DeprecationWarning, ) return Index.data(self, weighted, prune) @@ -200,26 +198,20 @@ def inserted_hs_indices(self, prune=False): if self.ndim == 2 and prune: # If pruning is applied, we need to subtract from the H&S indes # the number of pruned rows (cols) that come before that index. - pruning_bases = [ - self._pruning_base(axis=i, hs_dims=[0, 1]) - for i in [1, 0] - ] + pruning_bases = [self._pruning_base(axis=i, hs_dims=[0, 1]) for i in [1, 0]] pruning_bases = [ base if base.ndim == 1 else np.sum(base, axis=(1 - i)) for i, base in enumerate(pruning_bases) ] # Obtain prune indices as subscripts prune_indices_list = [ - np.arange(len(base))[ - np.logical_or(base == 0, np.isnan(base)) - ] + np.arange(len(base))[np.logical_or(base == 0, np.isnan(base))] for base in pruning_bases ] - inserted_indices_list = [ - dim.inserted_hs_indices for dim in self.dimensions - ] - return self._adjust_inserted_indices(inserted_indices_list, - prune_indices_list) + inserted_indices_list = [dim.inserted_hs_indices for dim in self.dimensions] + return self._adjust_inserted_indices( + inserted_indices_list, prune_indices_list + ) return [dim.inserted_hs_indices for dim in self.dimensions] @@ -231,10 +223,7 @@ def is_double_mr(self): @lazyproperty def is_univariate_ca(self): """True if cube only contains a CA dimension-pair, in either order.""" - return ( - self.ndim == 2 and - set(self.dim_types) == {DT.CA_SUBVAR, DT.CA_CAT} - ) + return self.ndim == 2 and set(self.dim_types) == {DT.CA_SUBVAR, DT.CA_CAT} @lazyproperty def is_weighted(self): @@ -255,8 +244,14 @@ def labels(self, include_missing=False, include_transforms_for_dims=False): for dim in self.dimensions ] - def margin(self, axis=None, weighted=True, include_missing=False, - include_transforms_for_dims=None, prune=False): + def margin( + self, + axis=None, + weighted=True, + include_missing=False, + include_transforms_for_dims=None, + prune=False, + ): """Get margin for the selected axis. the selected axis. For MR variables, this is the sum of the selected @@ -324,8 +319,7 @@ def hs_dims_for_den(hs_dims, axis): table = self._counts(weighted).raw_cube_array new_axis = self._adjust_axis(axis) index = tuple( - None if i in new_axis else slice(None) - for i, _ in enumerate(table.shape) + None if i in new_axis else slice(None) for i, _ in enumerate(table.shape) ) # Calculate denominator. Only include those H&S dimensions, across @@ -339,8 +333,7 @@ def hs_dims_for_den(hs_dims, axis): # Apply correct mask (based on the as_array shape) arr = self._as_array( - include_transforms_for_dims=hs_dims, - include_missing=include_missing + include_transforms_for_dims=hs_dims, include_missing=include_missing ) # ---prune array if pruning was requested--- @@ -360,25 +353,23 @@ def hs_dims_for_den(hs_dims, axis): ( None if ( - d.dimension_type == DT.MR_CAT or - i != 0 and ( - n <= 1 or - len(d.elements()) <= 1 - ) - ) else - slice(None) + d.dimension_type == DT.MR_CAT + or i != 0 + and (n <= 1 or len(d.elements()) <= 1) + ) + else slice(None) ) - for i, (d, n) in - enumerate(zip(self._all_dimensions, table.shape)) - ) - mask = np.logical_or( - np.zeros(den.shape, dtype=bool), - arr.mask[inflate_ind], + for i, (d, n) in enumerate(zip(self._all_dimensions, table.shape)) ) + mask = np.logical_or(np.zeros(den.shape, dtype=bool), arr.mask[inflate_ind]) den = np.ma.masked_array(den, mask) - if (self.ndim != 1 or axis is None or - axis == 0 and len(self._all_dimensions) == 1): + if ( + self.ndim != 1 + or axis is None + or axis == 0 + and len(self._all_dimensions) == 1 + ): # Special case for 1D cube wigh MR, for "Table" direction den = np.sum(den, axis=new_axis)[index] @@ -407,7 +398,8 @@ def mr_dim_ind(self): # this as it's really a cube internal characteristic. # TODO: Make this return a tuple in all cases, like (), (1,), or (0, 2). indices = tuple( - idx for idx, d in enumerate(self.dimensions) + idx + for idx, d in enumerate(self.dimensions) if d.dimension_type == DT.MR_SUBVAR ) if indices == (): @@ -474,9 +466,14 @@ def percentages(self, axis=None): """ return self.proportions(axis) * 100 - def population_counts(self, population_size, weighted=True, - include_missing=False, - include_transforms_for_dims=None, prune=False): + def population_counts( + self, + population_size, + weighted=True, + include_missing=False, + include_transforms_for_dims=None, + prune=False, + ): """Return counts scaled in proportion to overall population. The return value is a numpy.ndarray object. Count values are scaled @@ -499,12 +496,16 @@ def population_counts(self, population_size, weighted=True, [3000, 1800], ]) """ - return self.proportions( - weighted=weighted, - include_missing=include_missing, - include_transforms_for_dims=include_transforms_for_dims, - prune=prune - ) * population_size * self.population_fraction + return ( + self.proportions( + weighted=weighted, + include_missing=include_missing, + include_transforms_for_dims=include_transforms_for_dims, + prune=prune, + ) + * population_size + * self.population_fraction + ) @lazyproperty def population_fraction(self): @@ -517,9 +518,14 @@ def population_fraction(self): """ return self._measures.population_fraction - def proportions(self, axis=None, weighted=True, - include_transforms_for_dims=None, include_missing=False, - prune=False): + def proportions( + self, + axis=None, + weighted=True, + include_transforms_for_dims=None, + include_missing=False, + prune=False, + ): """Return percentage values for cube as `numpy.ndarray`. This function calculates the proportions across the selected axis @@ -591,8 +597,7 @@ def hs_dims_for_den(hs_dims, axis): table = self._measure(weighted).raw_cube_array new_axis = self._adjust_axis(axis) index = tuple( - None if i in new_axis else slice(None) - for i, _ in enumerate(table.shape) + None if i in new_axis else slice(None) for i, _ in enumerate(table.shape) ) # Calculate denominator. Only include those H&S dimensions, across @@ -604,16 +609,13 @@ def hs_dims_for_den(hs_dims, axis): den = np.sum(den, axis=new_axis)[index] # Calculate numerator from table (include all H&S dimensions). - num = self._apply_missings_and_insertions( - table, include_transforms_for_dims - ) + num = self._apply_missings_and_insertions(table, include_transforms_for_dims) res = self._drop_mr_cat_dims(num / den) # Apply correct mask (based on the as_array shape) arr = self.as_array( - prune=prune, - include_transforms_for_dims=include_transforms_for_dims, + prune=prune, include_transforms_for_dims=include_transforms_for_dims ) if isinstance(arr, np.ma.core.MaskedArray): res = np.ma.masked_array(res, arr.mask) @@ -659,14 +661,12 @@ def scale_means(self, hs_dims=None, prune=False): # calculated by using its values). The result of it, however, # is a row. That's why we need to check the insertions on the # row dim (inserted columns). - if (scale_means[0] is not None and 1 in hs_dims and - inserted_indices[1]): + if scale_means[0] is not None and 1 in hs_dims and inserted_indices[1]: for i in inserted_indices[1]: scale_means[0] = np.insert(scale_means[0], i, np.nan) # Scale means 1 is a column, so we need to check # for row insertions. - if (scale_means[1] is not None and 0 in hs_dims and - inserted_indices[0]): + if scale_means[1] is not None and 0 in hs_dims and inserted_indices[0]: for i in inserted_indices[0]: scale_means[1] = np.insert(scale_means[1], i, np.nan) @@ -678,16 +678,12 @@ def scale_means(self, hs_dims=None, prune=False): for i, scale_means in enumerate(slices_means): if scale_means[0] is not None: row_mask = ( - mask.all(axis=0) - if self.ndim < 3 else - mask.all(axis=1)[i] + mask.all(axis=0) if self.ndim < 3 else mask.all(axis=1)[i] ) scale_means[0] = scale_means[0][~row_mask] if self.ndim > 1 and scale_means[1] is not None: col_mask = ( - mask.all(axis=1) - if self.ndim < 3 else - mask.all(axis=2)[i] + mask.all(axis=1) if self.ndim < 3 else mask.all(axis=2)[i] ) scale_means[1] = scale_means[1][~col_mask] return slices_means @@ -732,7 +728,7 @@ def _adjust_axis(self, axis): For more info on how it needs to operate, check the unit tests. """ if not self._is_axis_allowed(axis): - ca_error_msg = 'Direction {} not allowed (items dimension)' + ca_error_msg = "Direction {} not allowed (items dimension)" raise ValueError(ca_error_msg.format(axis)) if isinstance(axis, int): @@ -772,9 +768,7 @@ def _adjust_axis(self, axis): def _adjust_inserted_indices(inserted_indices_list, prune_indices_list): """Adjust inserted indices, if there are pruned elements.""" # Created a copy, to preserve cached property - updated_inserted = [ - [i for i in dim_inds] for dim_inds in inserted_indices_list - ] + updated_inserted = [[i for i in dim_inds] for dim_inds in inserted_indices_list] pruned_and_inserted = zip(prune_indices_list, updated_inserted) for prune_inds, inserted_inds in pruned_and_inserted: # Only prune indices if they're not H&S (inserted) @@ -795,12 +789,11 @@ def _all_dimensions(self): dimensions (basically the categories dimension of each MR dimension-pair is suppressed). """ - return AllDimensions( - dimension_dicts=self._cube_dict['result']['dimensions'] - ) + return AllDimensions(dimension_dicts=self._cube_dict["result"]["dimensions"]) - def _apply_missings_and_insertions(self, res, include_transforms_for_dims, - include_missing=False): + def _apply_missings_and_insertions( + self, res, include_transforms_for_dims, include_missing=False + ): """Return ndarray with missing and insertions as specified. The return value is the result of the following operations on *res*, @@ -835,21 +828,23 @@ def _apply_missings_and_insertions(self, res, include_transforms_for_dims, continue apparent_dim_idx = dim_idx - suppressed_dim_count transform = ( - dim.has_transforms and - apparent_dim_idx in include_transforms_for_dims + dim.has_transforms and apparent_dim_idx in include_transforms_for_dims ) if not transform: continue # ---insert subtotals into result array--- insertions = self._insertions(res, dim, dim_idx) - res, new_valids = self._update_result( - res, insertions, dim_idx, new_valids - ) + res, new_valids = self._update_result(res, insertions, dim_idx, new_valids) return res[np.ix_(*new_valids)] if new_valids else res - def _as_array(self, include_missing=False, get_non_selected=False, - weighted=True, include_transforms_for_dims=False): + def _as_array( + self, + include_missing=False, + get_non_selected=False, + weighted=True, + include_transforms_for_dims=False, + ): """Get crunch cube as ndarray. Args @@ -864,7 +859,7 @@ def _as_array(self, include_missing=False, get_non_selected=False, return self._apply_missings_and_insertions( self._measure(weighted).raw_cube_array, include_transforms_for_dims, - include_missing=include_missing + include_missing=include_missing, ) @classmethod @@ -878,7 +873,7 @@ def _calculate_constraints_sum(cls, prop_table, prop_margin, axis): across i and j indices). """ if axis not in [0, 1]: - raise ValueError('Unexpected value for `axis`: {}'.format(axis)) + raise ValueError("Unexpected value for `axis`: {}".format(axis)) V = prop_table * (1 - prop_table) if axis == 0: @@ -905,18 +900,15 @@ def _counts(self, weighted): is not considered. Contrast with `._measure()` below. """ return ( - self._measures.weighted_counts if weighted else - self._measures.unweighted_counts + self._measures.weighted_counts + if weighted + else self._measures.unweighted_counts ) @staticmethod def _create_mask(res, row_prune_inds, col_prune_inds): - mask_rows = np.repeat( - row_prune_inds[:, None], len(col_prune_inds), axis=1 - ) - mask_cols = np.repeat( - col_prune_inds[None, :], len(row_prune_inds), axis=0 - ) + mask_rows = np.repeat(row_prune_inds[:, None], len(col_prune_inds), axis=1) + mask_cols = np.repeat(col_prune_inds[None, :], len(row_prune_inds), axis=0) return np.logical_or(mask_rows, mask_cols) @lazyproperty @@ -926,15 +918,16 @@ def _cube_dict(self): cube_response = self._cube_response_arg # ---parse JSON to a dict when constructed with JSON--- cube_dict = ( - cube_response if isinstance(cube_response, dict) + cube_response + if isinstance(cube_response, dict) else json.loads(cube_response) ) # ---cube is 'value' item in a shoji response--- - return cube_dict.get('value', cube_dict) + return cube_dict.get("value", cube_dict) except TypeError: raise TypeError( - 'Unsupported type <%s> provided. Cube response must be JSON ' - '(str) or dict.' % type(self._cube_response_arg).__name__ + "Unsupported type <%s> provided. Cube response must be JSON " + "(str) or dict." % type(self._cube_response_arg).__name__ ) def _drop_mr_cat_dims(self, array, fix_valids=False): @@ -970,21 +963,28 @@ def _drop_mr_cat_dims(self, array, fix_valids=False): # up to here. At this point, we need to remove the non-selected part of # selections dimension (and subsequently purge the dimension itself). - display_ind = tuple( - 0 if dim.dimension_type == DT.MR_CAT else slice(None) - for dim, n in zip(self._all_dimensions, array.shape) - ) if not fix_valids else np.ix_(*[ - dim.element_indices(include_missing=False) if n > 1 else [0] - for dim, n in zip(self._all_dimensions, array.shape) - ]) + display_ind = ( + tuple( + 0 if dim.dimension_type == DT.MR_CAT else slice(None) + for dim, n in zip(self._all_dimensions, array.shape) + ) + if not fix_valids + else np.ix_( + *[ + dim.element_indices(include_missing=False) if n > 1 else [0] + for dim, n in zip(self._all_dimensions, array.shape) + ] + ) + ) array = array[display_ind] # If a first dimension only has one element, we don't want to # remove it from the shape. Hence the i == 0 part. For other dimensions # that have one element, it means that these are the remnants of the MR # selections, which we don't need as separate dimensions. - new_shape = [length for (i, length) in enumerate(array.shape) - if length != 1 or i == 0] + new_shape = [ + length for (i, length) in enumerate(array.shape) if length != 1 or i == 0 + ] return array.reshape(new_shape) @classmethod @@ -1018,17 +1018,19 @@ def _insertions(self, result, dimension, dimension_index): def iter_insertions(): for anchor_idx, addend_idxs in dimension.hs_indices: insertion_idx = ( - -1 if anchor_idx == 'top' else - result.shape[dimension_index] - 1 if anchor_idx == 'bottom' + -1 + if anchor_idx == "top" + else result.shape[dimension_index] - 1 + if anchor_idx == "bottom" else anchor_idx ) addend_fancy_idx = tuple( - [slice(None) for _ in range(dimension_index)] + - [np.array(addend_idxs)] + [slice(None) for _ in range(dimension_index)] + + [np.array(addend_idxs)] ) yield ( insertion_idx, - np.sum(result[addend_fancy_idx], axis=dimension_index) + np.sum(result[addend_fancy_idx], axis=dimension_index), ) return [insertion for insertion in iter_insertions()] @@ -1094,9 +1096,11 @@ def _measure(self, weighted): unweighted counts are returned. """ return ( - self._measures.means if self._measures.means is not None else - self._measures.weighted_counts if weighted else - self._measures.unweighted_counts + self._measures.means + if self._measures.means is not None + else self._measures.weighted_counts + if weighted + else self._measures.unweighted_counts ) @lazyproperty @@ -1119,12 +1123,8 @@ def _prune_3d_body(self, res, transforms): for i, prune_inds in enumerate(self._prune_indices(transforms)): rows_pruned = prune_inds[0] cols_pruned = prune_inds[1] - rows_pruned = np.repeat( - rows_pruned[:, None], len(cols_pruned), axis=1 - ) - cols_pruned = np.repeat( - cols_pruned[None, :], len(rows_pruned), axis=0 - ) + rows_pruned = np.repeat(rows_pruned[:, None], len(cols_pruned), axis=1) + cols_pruned = np.repeat(cols_pruned[None, :], len(rows_pruned), axis=0) slice_mask = np.logical_or(rows_pruned, cols_pruned) # In case of MRs we need to "inflate" mask @@ -1146,12 +1146,10 @@ def _prune_3d_body(self, res, transforms): def _prune_3d_indices(self, transforms): row_margin = self._pruning_base( - hs_dims=transforms, - axis=self.row_direction_axis + hs_dims=transforms, axis=self.row_direction_axis ) col_margin = self._pruning_base( - hs_dims=transforms, - axis=self._col_direction_axis, + hs_dims=transforms, axis=self._col_direction_axis ) return [ self._prune_indices_tuple(rm, cm, transforms) @@ -1172,13 +1170,11 @@ def _prune_body(self, res, transforms=None): # ---determine which rows should be pruned--- row_margin = self._pruning_base( - hs_dims=transforms, - axis=self.row_direction_axis, + hs_dims=transforms, axis=self.row_direction_axis ) # ---adjust special-case row-margin values--- item_types = (DT.MR, DT.CA_SUBVAR) - if (self.ndim > 1 and self.dim_types[1] in item_types and - len(res.shape) > 1): + if self.ndim > 1 and self.dim_types[1] in item_types and len(res.shape) > 1: # ---when row-dimension has only one category it gets squashed--- axis = 1 if res.shape[0] > 1 else None # ---in CAT x MR case (or if it has CA subvars) we get @@ -1195,8 +1191,7 @@ def _prune_body(self, res, transforms=None): # ---determine which columns should be pruned--- col_margin = self._pruning_base( - hs_dims=transforms, - axis=self._col_direction_axis, + hs_dims=transforms, axis=self._col_direction_axis ) if col_margin.ndim > 1: # In case of MR x CAT, we have 2D margin @@ -1233,8 +1228,7 @@ def _prune_indices(self, transforms=None): def prune_non_3d_indices(transforms): row_margin = self._pruning_base( - hs_dims=transforms, - axis=self.row_direction_axis, + hs_dims=transforms, axis=self.row_direction_axis ) row_indices = self._margin_pruned_indices( row_margin, self._inserted_dim_inds(transforms, 0), 0 @@ -1248,8 +1242,7 @@ def prune_non_3d_indices(transforms): return [row_indices] col_margin = self._pruning_base( - hs_dims=transforms, - axis=self._col_direction_axis, + hs_dims=transforms, axis=self._col_direction_axis ) col_indices = self._margin_pruned_indices( @@ -1292,21 +1285,17 @@ def _pruning_base(self, axis=None, hs_dims=None): # In case we encountered axis that would go across items dimension, # we need to return at least some result, to prevent explicitly # checking for this condition, wherever self._margin is used - return self.as_array( - weighted=False, include_transforms_for_dims=hs_dims - ) + return self.as_array(weighted=False, include_transforms_for_dims=hs_dims) # In case of allowed axis, just return the normal API margin. This call # would throw an exception when directly invoked with bad axis. This is # intended, because we want to be as explicit as possible. Margins # across items are not allowed. return self.margin( - axis=axis, weighted=False, - include_transforms_for_dims=hs_dims, + axis=axis, weighted=False, include_transforms_for_dims=hs_dims ) - def _update_result(self, result, insertions, dimension_index, - valid_indices): + def _update_result(self, result, insertions, dimension_index, valid_indices): """Insert subtotals into resulting ndarray.""" # TODO: valid_indices should be a tuple as a parameter and as a return # value @@ -1314,11 +1303,8 @@ def _update_result(self, result, insertions, dimension_index, result = np.insert( result, ind_insertion + j + 1, value, axis=dimension_index ) - valid_indices = ( - valid_indices and - self._fix_valid_indices( - valid_indices, ind_insertion + j, dimension_index - ) + valid_indices = valid_indices and self._fix_valid_indices( + valid_indices, ind_insertion + j, dimension_index ) return result, valid_indices @@ -1338,16 +1324,14 @@ def is_weighted(self): any other measures provided by the cube. """ cube_dict = self._cube_dict - if cube_dict.get('query', {}).get('weight') is not None: + if cube_dict.get("query", {}).get("weight") is not None: return True - if cube_dict.get('weight_var') is not None: + if cube_dict.get("weight_var") is not None: return True - if cube_dict.get('weight_url') is not None: + if cube_dict.get("weight_url") is not None: return True - unweighted_counts = cube_dict['result']['counts'] - count_data = ( - cube_dict['result']['measures'].get('count', {}).get('data') - ) + unweighted_counts = cube_dict["result"]["counts"] + count_data = cube_dict["result"]["measures"].get("count", {}).get("data") if unweighted_counts != count_data: return True return False @@ -1359,10 +1343,7 @@ def means(self): None when the cube response does not contain a mean measure. """ mean_measure_dict = ( - self._cube_dict - .get('result', {}) - .get('measures', {}) - .get('mean') + self._cube_dict.get("result", {}).get("measures", {}).get("mean") ) if mean_measure_dict is None: return None @@ -1373,7 +1354,7 @@ def missing_count(self): """numeric representing count of missing rows in cube response.""" if self.means: return self.means.missing_count - return self._cube_dict['result'].get('missing', 0) + return self._cube_dict["result"].get("missing", 0) @lazyproperty def population_fraction(self): @@ -1384,16 +1365,8 @@ def population_fraction(self): Returns `np.nan` if the unfiltered count is zero, which would otherwise result in a divide-by-zero error. """ - numerator = ( - self._cube_dict['result'] - .get('filtered', {}) - .get('weighted_n') - ) - denominator = ( - self._cube_dict['result'] - .get('unfiltered', {}) - .get('weighted_n') - ) + numerator = self._cube_dict["result"].get("filtered", {}).get("weighted_n") + denominator = self._cube_dict["result"].get("unfiltered", {}).get("weighted_n") try: return numerator / denominator except ZeroDivisionError: @@ -1413,7 +1386,7 @@ def unweighted_counts(self): @lazyproperty def unweighted_n(self): """int count of actual rows represented by query response.""" - return self._cube_dict['result']['n'] + return self._cube_dict["result"]["n"] @lazyproperty def weighted_counts(self): @@ -1432,9 +1405,7 @@ def weighted_n(self): """float count of returned rows adjusted for weighting.""" if not self.is_weighted: return float(self.unweighted_n) - return float( - sum(self._cube_dict['result']['measures']['count']['data']) - ) + return float(sum(self._cube_dict["result"]["measures"]["count"]["data"])) class _BaseMeasure(object): @@ -1463,7 +1434,7 @@ def _flat_values(self): This property must be implemented by each subclass. """ - raise NotImplementedError('must be implemented by each subclass') + raise NotImplementedError("must be implemented by each subclass") class _MeanMeasure(_BaseMeasure): @@ -1472,9 +1443,7 @@ class _MeanMeasure(_BaseMeasure): @lazyproperty def missing_count(self): """numeric representing count of missing rows reflected in response.""" - return ( - self._cube_dict['result']['measures']['mean'].get('n_missing', 0) - ) + return self._cube_dict["result"]["measures"]["mean"].get("n_missing", 0) @lazyproperty def _flat_values(self): @@ -1486,7 +1455,7 @@ def _flat_values(self): """ return tuple( np.nan if type(x) is dict else x - for x in self._cube_dict['result']['measures']['mean']['data'] + for x in self._cube_dict["result"]["measures"]["mean"]["data"] ) @@ -1496,7 +1465,7 @@ class _UnweightedCountMeasure(_BaseMeasure): @lazyproperty def _flat_values(self): """tuple of int counts before weighting.""" - return tuple(self._cube_dict['result']['counts']) + return tuple(self._cube_dict["result"]["counts"]) class _WeightedCountMeasure(_BaseMeasure): @@ -1505,4 +1474,4 @@ class _WeightedCountMeasure(_BaseMeasure): @lazyproperty def _flat_values(self): """tuple of numeric counts after weighting.""" - return tuple(self._cube_dict['result']['measures']['count']['data']) + return tuple(self._cube_dict["result"]["measures"]["count"]["data"]) diff --git a/src/cr/cube/cube_slice.py b/src/cr/cube/cube_slice.py index 13f6748d4..ced2aae4c 100644 --- a/src/cr/cube/cube_slice.py +++ b/src/cr/cube/cube_slice.py @@ -32,8 +32,8 @@ def __init__(self, cube, index, ca_as_0th=False): if ca_as_0th and cube.dim_types[0] != DT.CA_SUBVAR: msg = ( - 'Cannot set CA as 0th for cube that ' - 'does not have CA items as the 0th dimension.' + "Cannot set CA as 0th for cube that " + "does not have CA items as the 0th dimension." ) raise ValueError(msg) @@ -53,9 +53,7 @@ def __getattr__(self, attr): # API properties get_only_last_two = ( - self._cube.ndim == 3 and - hasattr(cube_attr, '__len__') and - attr != 'name' + self._cube.ndim == 3 and hasattr(cube_attr, "__len__") and attr != "name" ) if get_only_last_two: return cube_attr[-2:] @@ -72,10 +70,10 @@ def __repr__(self): """ try: name = self.table_name if self.table_name else self.name - dimensionality = ' x '.join(dt.name for dt in self.dim_types) - dim_names = ' x '.join(d.name for d in self.dimensions) + dimensionality = " x ".join(dt.name for dt in self.dim_types) + dim_names = " x ".join(d.name for d in self.dimensions) labels = self.labels() - headers = labels[1] if len(labels) > 1 else ['N'] + headers = labels[1] if len(labels) > 1 else ["N"] tbl = ( self.as_array() if len(self.as_array().shape) > 1 @@ -83,11 +81,14 @@ def __repr__(self): ) body = tabulate( [[lbl] + lst for lbl, lst in zip(labels[0], tbl.tolist())], - headers=headers + headers=headers, ) - return ( - "%s(name='%s', dim_types='%s', dims='%s')\n%s" % - (type(self).__name__, name, dimensionality, dim_names, body) + return "%s(name='%s', dim_types='%s', dims='%s')\n%s" % ( + type(self).__name__, + name, + dimensionality, + dim_names, + body, ) except Exception: return super(CubeSlice, self).__repr__() @@ -165,14 +166,15 @@ def index_table(self, axis=None, baseline=None, prune=False): """ proportions = self.proportions(axis=axis) baseline = ( - baseline - if baseline is not None else - self._prepare_index_baseline(axis) + baseline if baseline is not None else self._prepare_index_baseline(axis) ) # Fix the shape to enable correct broadcasting - if (axis == 0 and len(baseline.shape) <= 1 and - self.ndim == len(self.get_shape())): + if ( + axis == 0 + and len(baseline.shape) <= 1 + and self.ndim == len(self.get_shape()) + ): baseline = baseline[:, None] indexes = proportions / baseline * 100 @@ -201,16 +203,14 @@ def labels(self, hs_dims=None, prune=False): def prune_dimension_labels(labels, prune_indices): """Get pruned labels for single dimension, besed on prune inds.""" - labels = [ - label for label, prune in zip(labels, prune_indices) - if not prune - ] + labels = [label for label, prune in zip(labels, prune_indices) if not prune] return labels labels = [ prune_dimension_labels(dim_labels, dim_prune_inds) - for dim_labels, dim_prune_inds in - zip(labels, self._prune_indices(transforms=hs_dims)) + for dim_labels, dim_prune_inds in zip( + labels, self._prune_indices(transforms=hs_dims) + ) ] return labels @@ -283,7 +283,7 @@ def shape(self): This property is deprecated, use 'get_shape' instead. Pruning is not supported (supported in 'get_shape'). """ - deprecation_msg = 'Deprecated. Use `get_shape` instead.' + deprecation_msg = "Deprecated. Use `get_shape` instead." warnings.warn(deprecation_msg, DeprecationWarning) return self.get_shape() @@ -300,7 +300,7 @@ def table_name(self): title = self._cube.name table_name = self._cube.labels()[0][self._index] - return '%s: %s' % (title, table_name) + return "%s: %s" % (title, table_name) def pvals(self, weighted=True, prune=False, hs_dims=None): """Return 2D ndarray with calculated p-vals. @@ -335,9 +335,7 @@ def zscore(self, weighted=True, prune=False, hs_dims=None): total = self.margin(weighted=weighted) colsum = self.margin(axis=0, weighted=weighted) rowsum = self.margin(axis=1, weighted=weighted) - zscore = self._calculate_std_res( - counts, total, colsum, rowsum, - ) + zscore = self._calculate_std_res(counts, total, colsum, rowsum) if hs_dims: zscore = self._intersperse_hs_in_std_res(hs_dims, zscore) @@ -375,10 +373,7 @@ def _array_type_std_res(self, counts, total, colsum, rowsum): rowsum = rowsum[:, np.newaxis] expected_counts = rowsum * colsum / total - variance = ( - rowsum * colsum * (total - rowsum) * (total - colsum) / - total ** 3 - ) + variance = rowsum * colsum * (total - rowsum) * (total - colsum) / total ** 3 return (counts - expected_counts) / np.sqrt(variance) def _calculate_std_res(self, counts, total, colsum, rowsum): @@ -393,7 +388,7 @@ def _calculate_std_res(self, counts, total, colsum, rowsum): def _call_cube_method(self, method, *args, **kwargs): kwargs = self._update_args(kwargs) result = getattr(self._cube, method)(*args, **kwargs) - if method == 'inserted_hs_indices': + if method == "inserted_hs_indices": if not self.ca_as_0th: result = result[-2:] return result @@ -429,16 +424,8 @@ def _prepare_index_baseline(self, axis): total_axis = axis + 1 slice_ += [slice(None), 0] if axis == 1 else [0] elif self.mr_dim_ind is not None: - slice_ = ( - [0] - if self.mr_dim_ind == 0 and axis != 0 else - [slice(None), 0] - ) - total_axis = ( - axis - if self.mr_dim_ind != 0 else - 1 - axis - ) + slice_ = [0] if self.mr_dim_ind == 0 and axis != 0 else [slice(None), 0] + total_axis = axis if self.mr_dim_ind != 0 else 1 - axis total = np.sum(baseline, axis=total_axis) baseline = baseline[slice_] @@ -460,8 +447,9 @@ def _scalar_type_std_res(self, counts, total, colsum, rowsum): expected_counts = expected_freq(counts) residuals = counts - expected_counts variance = ( - np.outer(rowsum, colsum) * - np.outer(total - rowsum, total - colsum) / total ** 3 + np.outer(rowsum, colsum) + * np.outer(total - rowsum, total - colsum) + / total ** 3 ) return residuals / np.sqrt(variance) @@ -471,19 +459,19 @@ def _update_args(self, kwargs): # In this case we don't need to convert any arguments, but just # pass them to the underlying cube (which is the slice). if self.ca_as_0th: - axis = kwargs.get('axis', False) + axis = kwargs.get("axis", False) if axis is None: # Special case for CA slices (in multitables). In this case, # we need to calculate a measurement across CA categories # dimension (and not across items, because it's not # allowed). The value for the axis parameter of None, would # incur the items dimension, and we don't want that. - kwargs['axis'] = 1 + kwargs["axis"] = 1 return kwargs # Handling API methods that include 'axis' parameter - axis = kwargs.get('axis') + axis = kwargs.get("axis") # Expected usage of the 'axis' parameter from CubeSlice is 0, 1, or # None. CrunchCube handles all other logic. The only 'smart' thing # about the handling here, is that the axes are increased for 3D cubes. @@ -495,7 +483,7 @@ def _update_args(self, kwargs): # If the user provides a tuple, it's considered that he "knows" what # he's doing, and the axis argument is not updated in this case. if isinstance(axis, int): - kwargs['axis'] += 1 + kwargs["axis"] += 1 # Handling API methods that include H&S parameter @@ -506,9 +494,11 @@ def _update_args(self, kwargs): # (from the perspective of the cr.exporter) is to exclude the 0th # dimension's H&S in the case of 3D cubes. hs_dims_key = ( - 'transforms' in kwargs and 'transforms' or - 'hs_dims' in kwargs and 'hs_dims' or - 'include_transforms_for_dims' + "transforms" in kwargs + and "transforms" + or "hs_dims" in kwargs + and "hs_dims" + or "include_transforms_for_dims" ) hs_dims = kwargs.get(hs_dims_key) if isinstance(hs_dims, list): @@ -522,8 +512,7 @@ def _update_args(self, kwargs): return kwargs def _update_result(self, result): - if (self._cube.ndim < 3 and not self.ca_as_0th or - len(result) - 1 < self._index): + if self._cube.ndim < 3 and not self.ca_as_0th or len(result) - 1 < self._index: return result result = result[self._index] if isinstance(result, tuple): diff --git a/src/cr/cube/dimension.py b/src/cr/cube/dimension.py index bf078ad5d..24574fe53 100644 --- a/src/cr/cube/dimension.py +++ b/src/cr/cube/dimension.py @@ -32,7 +32,7 @@ def _dimensions(self): This composed tuple is the source for the dimension objects in this collection. """ - raise NotImplementedError('must be implemented by each sublass') + raise NotImplementedError("must be implemented by each sublass") class AllDimensions(_BaseDimensions): @@ -67,9 +67,7 @@ def _dimensions(self): This composed tuple is the internal source for the dimension objects in this collection. """ - return tuple( - _DimensionFactory.iter_dimensions(self._dimension_dicts) - ) + return tuple(_DimensionFactory.iter_dimensions(self._dimension_dicts)) class _ApparentDimensions(_BaseDimensions): @@ -85,10 +83,7 @@ def _dimensions(self): This composed tuple is the source for the dimension objects in this collection. """ - return tuple( - d for d in self._all_dimensions - if d.dimension_type != DT.MR_CAT - ) + return tuple(d for d in self._all_dimensions if d.dimension_type != DT.MR_CAT) class _DimensionFactory(object): @@ -110,10 +105,7 @@ def iter_dimensions(cls, dimension_dicts): def _iter_dimensions(self): """Generate Dimension object for each dimension dict.""" return ( - Dimension( - raw_dimension.dimension_dict, - raw_dimension.dimension_type - ) + Dimension(raw_dimension.dimension_dict, raw_dimension.dimension_type) for raw_dimension in self._raw_dimensions ) @@ -147,24 +139,22 @@ def dimension_dict(self): def dimension_type(self): """Return member of DIMENSION_TYPE appropriate to dimension_dict.""" base_type = self._base_type - if base_type == 'categorical': + if base_type == "categorical": return self._resolve_categorical() - if base_type == 'enum.variable': + if base_type == "enum.variable": return self._resolve_array_type() - if base_type == 'enum.datetime': + if base_type == "enum.datetime": return DT.DATETIME - if base_type == 'enum.numeric': + if base_type == "enum.numeric": return DT.BINNED_NUMERIC - if base_type == 'enum.text': + if base_type == "enum.text": return DT.TEXT - raise NotImplementedError( - 'unrecognized dimension type %s' % base_type - ) + raise NotImplementedError("unrecognized dimension type %s" % base_type) @lazyproperty def _alias(self): """Return str key for variable behind *dimension_dict*.""" - return self._dimension_dict['references']['alias'] + return self._dimension_dict["references"]["alias"] @lazyproperty def _base_type(self): @@ -174,15 +164,13 @@ def _base_type(self): used to identify the dimension type in the cube response JSON. The '.subclass' suffix only appears where a subtype is present. """ - type_class = self._dimension_dict['type']['class'] - if type_class == 'categorical': - return 'categorical' - if type_class == 'enum': - subclass = self._dimension_dict['type']['subtype']['class'] - return 'enum.%s' % subclass - raise NotImplementedError( - 'unexpected dimension type class \'%s\'' % type_class - ) + type_class = self._dimension_dict["type"]["class"] + if type_class == "categorical": + return "categorical" + if type_class == "enum": + subclass = self._dimension_dict["type"]["subtype"]["class"] + return "enum.%s" % subclass + raise NotImplementedError("unexpected dimension type class '%s'" % type_class) @lazyproperty def _has_selected_category(self): @@ -192,8 +180,8 @@ def _has_selected_category(self): property is only meaningful for a categorical dimension dict. """ return True in { - category.get('selected') - for category in self._dimension_dict['type'].get('categories', []) + category.get("selected") + for category in self._dimension_dict["type"].get("categories", []) } @lazyproperty @@ -204,7 +192,7 @@ def _is_array_cat(self): the dimension is known to be categorical (has base-type 'categorical'). """ - return 'subreferences' in self._dimension_dict['references'] + return "subreferences" in self._dimension_dict["references"] @lazyproperty def _next_raw_dimension(self): @@ -216,9 +204,7 @@ def _next_raw_dimension(self): this_idx = dimension_dicts.index(self._dimension_dict) if this_idx > len(dimension_dicts) - 2: return None - return _RawDimension( - dimension_dicts[this_idx + 1], self._dimension_dicts - ) + return _RawDimension(dimension_dicts[this_idx + 1], self._dimension_dicts) def _resolve_array_type(self): """Return one of the ARRAY_TYPES members of DIMENSION_TYPE. @@ -232,9 +218,9 @@ def _resolve_array_type(self): return DT.CA is_mr_subvar = ( - next_raw_dimension._base_type == 'categorical' and - next_raw_dimension._has_selected_category and - next_raw_dimension._alias == self._alias + next_raw_dimension._base_type == "categorical" + and next_raw_dimension._has_selected_category + and next_raw_dimension._alias == self._alias ) return DT.MR if is_mr_subvar else DT.CA @@ -272,8 +258,8 @@ def __init__(self, dimension_dict, dimension_type): @lazyproperty def description(self): """str description of this dimension.""" - description = self._dimension_dict['references'].get('description') - return description if description else '' + description = self._dimension_dict["references"].get("description") + return description if description else "" @lazyproperty def dimension_type(self): @@ -288,16 +274,15 @@ def element_indices(self, include_missing): only valid element index values are returned. """ return ( - self._all_elements.element_idxs if include_missing else - self._valid_elements.element_idxs + self._all_elements.element_idxs + if include_missing + else self._valid_elements.element_idxs ) @memoize def elements(self, include_missing=False): """_Elements object providing access to elements of this dimension.""" - return ( - self._all_elements if include_missing else self._valid_elements - ) + return self._all_elements if include_missing else self._valid_elements @lazyproperty def has_transforms(self): @@ -325,8 +310,7 @@ def hs_indices(self): return () return tuple( - (subtotal.anchor_idx, subtotal.addend_idxs) - for subtotal in self._subtotals + (subtotal.anchor_idx, subtotal.addend_idxs) for subtotal in self._subtotals ) @lazyproperty @@ -341,8 +325,10 @@ def inserted_hs_indices(self): return [] return [ - idx for idx, item - in enumerate(self._iter_interleaved_items(self._valid_elements)) + idx + for idx, item in enumerate( + self._iter_interleaved_items(self._valid_elements) + ) if item.is_insertion ] @@ -351,8 +337,9 @@ def is_marginable(self): """True if adding counts across this dimension axis is meaningful.""" return self.dimension_type not in {DT.CA, DT.MR, DT.MR_CAT, DT.LOGICAL} - def labels(self, include_missing=False, include_transforms=False, - include_cat_ids=False): + def labels( + self, include_missing=False, include_transforms=False, include_cat_ids=False + ): """Return list of str labels for the elements of this dimension. Returns a list of (label, element_id) pairs if *include_cat_ids* is @@ -364,14 +351,9 @@ def labels(self, include_missing=False, include_transforms=False, # that effectively squashes what should be two methods into one. # Either get rid of the need for that alternate return value type or # create a separate method for it. - elements = ( - self._all_elements if include_missing else self._valid_elements - ) + elements = self._all_elements if include_missing else self._valid_elements - include_subtotals = ( - include_transforms and - self.dimension_type != DT.CA_SUBVAR - ) + include_subtotals = include_transforms and self.dimension_type != DT.CA_SUBVAR # ---items are elements or subtotals, interleaved in display order--- interleaved_items = tuple(self._iter_interleaved_items(elements)) @@ -395,8 +377,8 @@ def labels(self, include_missing=False, include_transforms=False, @lazyproperty def name(self): """Name of a cube's dimension.""" - refs = self._dimension_dict['references'] - return refs.get('name', refs.get('alias')) + refs = self._dimension_dict["references"] + return refs.get("name", refs.get("alias")) @lazyproperty def numeric_values(self): @@ -413,9 +395,7 @@ def numeric_values(self): a value, but an element with no numeric value appears as `np.nan` in the returned list. """ - return tuple( - element.numeric_value for element in self._valid_elements - ) + return tuple(element.numeric_value for element in self._valid_elements) @lazyproperty def shape(self): @@ -424,7 +404,7 @@ def shape(self): @lazyproperty def _all_elements(self): """_AllElements object providing cats or subvars of this dimension.""" - return _AllElements(self._dimension_dict['type']) + return _AllElements(self._dimension_dict["type"]) def _iter_interleaved_items(self, elements): """Generate element or subtotal items in interleaved order. @@ -440,7 +420,7 @@ def _iter_interleaved_items(self, elements): """ subtotals = self._subtotals - for subtotal in subtotals.iter_for_anchor('top'): + for subtotal in subtotals.iter_for_anchor("top"): yield subtotal for element in elements: @@ -448,7 +428,7 @@ def _iter_interleaved_items(self, elements): for subtotal in subtotals.iter_for_anchor(element.element_id): yield subtotal - for subtotal in subtotals.iter_for_anchor('bottom'): + for subtotal in subtotals.iter_for_anchor("bottom"): yield subtotal @lazyproperty @@ -458,11 +438,10 @@ def _subtotals(self): The subtotals sequence provides access to any subtotal insertions defined on this dimension. """ - view = self._dimension_dict.get('references', {}).get('view', {}) + view = self._dimension_dict.get("references", {}).get("view", {}) # ---view can be both None and {}, thus the edge case.--- insertion_dicts = ( - [] if view is None else - view.get('transform', {}).get('insertions', []) + [] if view is None else view.get("transform", {}).get("insertions", []) ) return _Subtotals(insertion_dicts, self._valid_elements) @@ -528,7 +507,7 @@ def _elements(self): Must be implemented by each subclass. """ - raise NotImplementedError('must be implemented by each subclass') + raise NotImplementedError("must be implemented by each subclass") @lazyproperty def _element_makings(self): @@ -538,9 +517,9 @@ def _element_makings(self): determines the type (class) and source dicts for the elements of this dimension and provides them for the element factory. """ - if self._type_dict['class'] == 'categorical': - return _Category, self._type_dict['categories'] - return _Element, self._type_dict['elements'] + if self._type_dict["class"] == "categorical": + return _Category, self._type_dict["categories"] + return _Element, self._type_dict["elements"] @lazyproperty def _elements_by_id(self): @@ -584,10 +563,7 @@ def __init__(self, all_elements): @lazyproperty def _elements(self): """tuple containing actual sequence of element objects.""" - return tuple( - element for element in self._all_elements - if not element.missing - ) + return tuple(element for element in self._all_elements if not element.missing) class _BaseElement(object): @@ -600,7 +576,7 @@ def __init__(self, element_dict, index): @lazyproperty def element_id(self): """int identifier for this category or subvariable.""" - return self._element_dict['id'] + return self._element_dict["id"] @lazyproperty def index(self): @@ -626,12 +602,12 @@ def missing(self): False if this category or subvariable represents valid (collected) data. """ - return bool(self._element_dict.get('missing')) + return bool(self._element_dict.get("missing")) @lazyproperty def numeric_value(self): """Numeric value assigned to element by user, np.nan if absent.""" - numeric_value = self._element_dict.get('numeric_value') + numeric_value = self._element_dict.get("numeric_value") return np.nan if numeric_value is None else numeric_value @@ -645,8 +621,8 @@ def __init__(self, category_dict, index): @lazyproperty def label(self): """str display name assigned to this category by user.""" - name = self._category_dict.get('name') - return name if name else '' + name = self._category_dict.get("name") + return name if name else "" class _Element(_BaseElement): @@ -659,25 +635,25 @@ def label(self): This property handles numeric, datetime and text variables, but also subvar dimensions """ - value = self._element_dict.get('value') + value = self._element_dict.get("value") type_name = type(value).__name__ - if type_name == 'NoneType': - return '' + if type_name == "NoneType": + return "" - if type_name == 'list': + if type_name == "list": # ---like '10-15' or 'A-F'--- - return '-'.join([str(item) for item in value]) + return "-".join([str(item) for item in value]) - if type_name in ('float', 'int'): + if type_name in ("float", "int"): return str(value) - if type_name in ('str', 'unicode'): + if type_name in ("str", "unicode"): return value # ---For CA and MR subvar dimensions--- - name = value.get('references', {}).get('name') - return name if name else '' + name = value.get("references", {}).get("name") + return name if name else "" class _Subtotals(Sequence): @@ -707,10 +683,7 @@ def __len__(self): def iter_for_anchor(self, anchor): """Generate each subtotal having matching *anchor*.""" - return ( - subtotal for subtotal in self._subtotals - if subtotal.anchor == anchor - ) + return (subtotal for subtotal in self._subtotals if subtotal.anchor == anchor) @lazyproperty def _element_ids(self): @@ -725,15 +698,15 @@ def _iter_valid_subtotal_dicts(self): continue # ---skip any non-subtotal insertions--- - if insertion_dict.get('function') != 'subtotal': + if insertion_dict.get("function") != "subtotal": continue # ---skip any malformed subtotal-dicts--- - if not {'anchor', 'args', 'name'}.issubset(insertion_dict.keys()): + if not {"anchor", "args", "name"}.issubset(insertion_dict.keys()): continue # ---skip if doesn't reference at least one non-missing element--- - if not self._element_ids.intersection(insertion_dict['args']): + if not self._element_ids.intersection(insertion_dict["args"]): continue # ---an insertion-dict that successfully runs this gauntlet @@ -768,11 +741,11 @@ def anchor(self): element that is no longer present in the dimension or an element that represents missing data. """ - anchor = self._subtotal_dict['anchor'] + anchor = self._subtotal_dict["anchor"] try: anchor = int(anchor) if anchor not in self._valid_elements.element_ids: - return 'bottom' + return "bottom" return anchor except (TypeError, ValueError): return anchor.lower() @@ -784,7 +757,7 @@ def anchor_idx(self): When the anchor is an operation, like 'top' or 'bottom' """ anchor = self.anchor - if anchor in ['top', 'bottom']: + if anchor in ["top", "bottom"]: return anchor return self._valid_elements.get_by_id(anchor).index @@ -796,7 +769,8 @@ def addend_ids(self): representing missing data is excluded. """ return tuple( - arg for arg in self._subtotal_dict.get('args', []) + arg + for arg in self._subtotal_dict.get("args", []) if arg in self._valid_elements.element_ids ) @@ -824,5 +798,5 @@ def is_insertion(self): @lazyproperty def label(self): """str display name for this subtotal, suitable for use as label.""" - name = self._subtotal_dict.get('name') - return name if name else '' + name = self._subtotal_dict.get("name") + return name if name else "" diff --git a/src/cr/cube/enum.py b/src/cr/cube/enum.py index f2b9322e9..68655245a 100644 --- a/src/cr/cube/enum.py +++ b/src/cr/cube/enum.py @@ -12,10 +12,10 @@ def __init__(self, name): self._name = name def __repr__(self): - return '' % self._name + return "" % self._name def __str__(self): - return 'DIMENSION_TYPE.%s' % self._name + return "DIMENSION_TYPE.%s" % self._name @lazyproperty def name(self): @@ -27,15 +27,15 @@ class DIMENSION_TYPE(object): """Enumerated values representing the various types of dimension.""" # ---member definitions--- - BINNED_NUMERIC = _DimensionType('BINNED_NUMERIC') - CAT = _DimensionType('CAT') - CA_CAT = _DimensionType('CA_CAT') - CA_SUBVAR = _DimensionType('CA_SUBVAR') - DATETIME = _DimensionType('DATETIME') - LOGICAL = _DimensionType('LOGICAL') - MR_CAT = _DimensionType('MR_CAT') - MR_SUBVAR = _DimensionType('MR_SUBVAR') - TEXT = _DimensionType('TEXT') + BINNED_NUMERIC = _DimensionType("BINNED_NUMERIC") + CAT = _DimensionType("CAT") + CA_CAT = _DimensionType("CA_CAT") + CA_SUBVAR = _DimensionType("CA_SUBVAR") + DATETIME = _DimensionType("DATETIME") + LOGICAL = _DimensionType("LOGICAL") + MR_CAT = _DimensionType("MR_CAT") + MR_SUBVAR = _DimensionType("MR_SUBVAR") + TEXT = _DimensionType("TEXT") # ---aliases--- CA = CA_SUBVAR diff --git a/src/cr/cube/measures/index.py b/src/cr/cube/measures/index.py index 93b125320..b7f995004 100644 --- a/src/cr/cube/measures/index.py +++ b/src/cr/cube/measures/index.py @@ -28,9 +28,7 @@ def _data(self, cube, weighted, prune): num = slice_.margin(axis=0, weighted=weighted, prune=prune) den = slice_.margin(weighted=weighted, prune=prune) margin = num / den - proportions = slice_.proportions( - axis=1, weighted=weighted, prune=prune - ) + proportions = slice_.proportions(axis=1, weighted=weighted, prune=prune) result.append(proportions / margin) if len(result) == 1 and cube.ndim < 3: @@ -47,12 +45,8 @@ def _data(self, cube, weighted, prune): def _mr_index(self, cube, weighted, prune): # mr by mr if len(cube.dimensions) == 2 and cube.mr_dim_ind == (0, 1): - col_proportions = cube.proportions( - axis=0, weighted=weighted, prune=prune - ) - row_proportions = cube.proportions( - axis=1, weighted=weighted, prune=prune - ) + col_proportions = cube.proportions(axis=0, weighted=weighted, prune=prune) + row_proportions = cube.proportions(axis=1, weighted=weighted, prune=prune) return col_proportions / row_proportions # mr by cat and cat by mr @@ -61,11 +55,9 @@ def _mr_index(self, cube, weighted, prune): num = cube.margin(axis=1 - axis, weighted=weighted, prune=prune) den = cube.margin(weighted=weighted, prune=prune) margin = num / den - proportions = cube.proportions( - axis=axis, weighted=weighted, prune=prune - ) + proportions = cube.proportions(axis=axis, weighted=weighted, prune=prune) if cube.mr_dim_ind == 0: margin = margin[:, np.newaxis] # pivot return proportions / margin - raise ValueError('Unexpected dimension types for cube with MR.') + raise ValueError("Unexpected dimension types for cube with MR.") diff --git a/src/cr/cube/measures/scale_means.py b/src/cr/cube/measures/scale_means.py index 5671a8f33..97c1dcceb 100644 --- a/src/cr/cube/measures/scale_means.py +++ b/src/cr/cube/measures/scale_means.py @@ -50,17 +50,17 @@ def data(self): return means def margin(self, axis): - '''Return marginal value of the current slice scaled means. + """Return marginal value of the current slice scaled means. This value is the the same what you would get from a single variable (constituting a 2D cube/slice), when the "non-missing" filter of the opposite variable would be applied. This behavior is consistent with what is visible in the front-end client. - ''' + """ if self._slice.ndim < 2: msg = ( - 'Scale Means marginal cannot be calculated on 1D cubes, as' - 'the scale means already get reduced to a scalar value.' + "Scale Means marginal cannot be calculated on 1D cubes, as" + "the scale means already get reduced to a scalar value." ) raise ValueError(msg) @@ -82,7 +82,8 @@ def _valid_indices(self, axis): # --somewhere, like perhaps CrunchCube and/or # --CrunchSlice.reshaped_dimensions. reshaped_dimensions = [ - dimension for dimension in self._slice.dimensions + dimension + for dimension in self._slice.dimensions if len(dimension.numeric_values) > 1 ] @@ -90,9 +91,9 @@ def _valid_indices(self, axis): ( ~np.isnan(np.array(dim.numeric_values)) if ( - dim.numeric_values and - any(~np.isnan(dim.numeric_values)) and - axis == i + dim.numeric_values + and any(~np.isnan(dim.numeric_values)) + and axis == i ) else slice(None) ) @@ -109,21 +110,14 @@ def values(self): return [ ( np.array(dim.numeric_values) - if ( - dim.numeric_values and - any(~np.isnan(dim.numeric_values)) - ) + if (dim.numeric_values and any(~np.isnan(dim.numeric_values))) else None ) for dim in self._slice.dimensions ] def _inflate(self, dim_ind): - return ( - self._slice.ndim > 1 and - len(self._slice.get_shape()) > 1 and - not dim_ind - ) + return self._slice.ndim > 1 and len(self._slice.get_shape()) > 1 and not dim_ind def _inner_prods(self, contents, values): products = [] diff --git a/src/cr/cube/util.py b/src/cr/cube/util.py index 15c59253d..92ae68fe0 100644 --- a/src/cr/cube/util.py +++ b/src/cr/cube/util.py @@ -153,7 +153,7 @@ def __set__(self, obj, value): usec per access when measured on a 2.8GHz development machine; so quite snappy and probably not a rich target for optimization efforts. """ - raise AttributeError('can\'t set attribute') + raise AttributeError("can't set attribute") def lru_cache(maxsize=100): @@ -166,13 +166,14 @@ def lru_cache(maxsize=100): """ maxqueue = maxsize * 10 - def decorating_function(user_function, len=len, iter=iter, tuple=tuple, - sorted=sorted, KeyError=KeyError): - cache = {} # mapping of args to results + def decorating_function( + user_function, len=len, iter=iter, tuple=tuple, sorted=sorted, KeyError=KeyError + ): + cache = {} # mapping of args to results queue = collections.deque() # order that keys have been used - refcount = Counter() # times each key is in the queue - sentinel = object() # marker for looping around the queue - kwd_mark = object() # separate positional and keyword args + refcount = Counter() # times each key is in the queue + sentinel = object() # marker for looping around the queue + kwd_mark = object() # separate positional and keyword args # lookup optimizations (ugly but fast) queue_append, queue_popleft = queue.append, queue.popleft @@ -212,8 +213,9 @@ def wrapper(*args, **kwds): if len(queue) > maxqueue: refcount.clear() queue_appendleft(sentinel) - for key in ifilterfalse(refcount.__contains__, - iter(queue_pop, sentinel)): + for key in ifilterfalse( + refcount.__contains__, iter(queue_pop, sentinel) + ): queue_appendleft(key) refcount[key] = 1 @@ -228,6 +230,7 @@ def clear(): # pragma: no cover wrapper.hits = wrapper.misses = 0 wrapper.clear = clear return wrapper + return decorating_function diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py index c70fe75b2..d28b545f3 100644 --- a/tests/fixtures/__init__.py +++ b/tests/fixtures/__init__.py @@ -5,7 +5,7 @@ import json import os -CUBES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cubes') +CUBES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cubes") class LazyCubeResponseLoader(object): @@ -41,10 +41,7 @@ def _dirpath(self): def _json_path(self, fixture_name): """Return absolute path to JSON file for *fixture_name*.""" - return ( - '%s/%s.json' % - (self._dirpath, fixture_name.replace('_', '-').lower()) - ) + return "%s/%s.json" % (self._dirpath, fixture_name.replace("_", "-").lower()) def _load_json(self, path): """Return dict parsed from JSON at *path*.""" @@ -55,9 +52,9 @@ def _load_json(self, path): def _load_to_cache(self, fixture_name): json_path = self._json_path(fixture_name) if not os.path.exists(json_path): - raise ValueError('no JSON fixture found at %s' % json_path) + raise ValueError("no JSON fixture found at %s" % json_path) self._cache[fixture_name] = self._load_json(json_path) -CR = LazyCubeResponseLoader('.') # ---mnemonic: CR = 'cube-response'--- -SM = LazyCubeResponseLoader('./scale_means') +CR = LazyCubeResponseLoader(".") # ---mnemonic: CR = 'cube-response'--- +SM = LazyCubeResponseLoader("./scale_means") diff --git a/tests/integration/test_crunch_cube.py b/tests/integration/test_crunch_cube.py index 54450f6bc..4dfea6411 100644 --- a/tests/integration/test_crunch_cube.py +++ b/tests/integration/test_crunch_cube.py @@ -3,8 +3,11 @@ import pytest from cr.cube.crunch_cube import ( - CrunchCube, _MeanMeasure, _Measures, _UnweightedCountMeasure, - _WeightedCountMeasure + CrunchCube, + _MeanMeasure, + _Measures, + _UnweightedCountMeasure, + _WeightedCountMeasure, ) from cr.cube.enum import DIMENSION_TYPE as DT from cr.cube.measures.index import Index @@ -15,11 +18,10 @@ class DescribeIntegratedCrunchCube(object): - def it_provides_a_console_friendly_repr_for_a_cube(self): cube = CrunchCube(CR.CAT_X_CAT) repr_ = repr(cube) - assert repr_ == 'CrunchCube(name=\'v4\', dim_types=\'CAT x CAT\')' + assert repr_ == "CrunchCube(name='v4', dim_types='CAT x CAT')" def it_provides_access_to_its_dimensions(self, dimensions_fixture): cube_response, expected_dimension_types = dimensions_fixture @@ -52,28 +54,31 @@ def it_provides_pruned_array_for_CA_CAT_x_CA_SUBVAR(self): np.testing.assert_array_equal( compress_pruned(arr), np.array( - [[0.19012797074954296, 0.10494203782794387], - [0.2528945764777575, 0.2190359975594875], - [0.16514320536258378, 0.1720561317876754], - [0.29859841560024375, 0.4069554606467358], - [0.09323583180987204, 0.09701037217815742]] - ) + [ + [0.19012797074954296, 0.10494203782794387], + [0.2528945764777575, 0.2190359975594875], + [0.16514320536258378, 0.1720561317876754], + [0.29859841560024375, 0.4069554606467358], + [0.09323583180987204, 0.09701037217815742], + ] + ), ) # fixtures ------------------------------------------------------- - @pytest.fixture(params=[ - (CR.CA_SUBVAR_HS_X_MR_X_CA_CAT, (DT.CA_SUBVAR, DT.MR, DT.CA_CAT)), - (CR.CAT_X_LOGICAL, (DT.CAT, DT.LOGICAL)), - (CR.LOGICAL_UNIVARIATE, (DT.LOGICAL,)), - ]) + @pytest.fixture( + params=[ + (CR.CA_SUBVAR_HS_X_MR_X_CA_CAT, (DT.CA_SUBVAR, DT.MR, DT.CA_CAT)), + (CR.CAT_X_LOGICAL, (DT.CAT, DT.LOGICAL)), + (CR.LOGICAL_UNIVARIATE, (DT.LOGICAL,)), + ] + ) def dimensions_fixture(self, request): cube_response, expected_dimension_types = request.param return cube_response, expected_dimension_types class DescribeIntegrated_Measures(object): - def it_knows_when_its_measures_are_weighted(self, is_weighted_fixture): cube_dict, expected_value = is_weighted_fixture measures = _Measures(cube_dict, None) @@ -88,7 +93,7 @@ def it_provides_access_to_the_mean_measure(self): means = measures.means - assert type(means).__name__ == '_MeanMeasure' + assert type(means).__name__ == "_MeanMeasure" def but_only_when_the_cube_response_contains_means(self): cube_dict = CR.CAT_X_CAT @@ -121,15 +126,14 @@ def it_provides_access_to_the_unweighted_count_measure(self): unweighted_counts = measures.unweighted_counts - assert type(unweighted_counts).__name__ == '_UnweightedCountMeasure' + assert type(unweighted_counts).__name__ == "_UnweightedCountMeasure" def it_knows_the_unweighted_n(self): measures = _Measures(CR.CAT_X_CAT, None) unweighted_n = measures.unweighted_n assert unweighted_n == 20 - def it_provides_access_to_the_weighted_count_measure( - self, wgtd_counts_fixture): + def it_provides_access_to_the_weighted_count_measure(self, wgtd_counts_fixture): cube_dict, expected_type_name = wgtd_counts_fixture measures = _Measures(cube_dict, None) @@ -147,52 +151,59 @@ def it_knows_the_weighted_n(self, wgtd_n_fixture): # fixtures ------------------------------------------------------- - @pytest.fixture(params=[ - # ---has {'query': {'weight': url}}--- - (CR.ADMIT_X_GENDER_WEIGHTED, True), - # ---has {'weight_var': weight_name_str}--- - (CR.CAT_X_CAT_X_CAT_WGTD, True), - # ---unweighted_counts == measure_count_data--- - (CR.ADMIT_X_DEPT_UNWEIGHTED, False), - ]) + @pytest.fixture( + params=[ + # ---has {'query': {'weight': url}}--- + (CR.ADMIT_X_GENDER_WEIGHTED, True), + # ---has {'weight_var': weight_name_str}--- + (CR.CAT_X_CAT_X_CAT_WGTD, True), + # ---unweighted_counts == measure_count_data--- + (CR.ADMIT_X_DEPT_UNWEIGHTED, False), + ] + ) def is_weighted_fixture(self, request): cube_response, expected_value = request.param - cube_dict = cube_response.get('value', cube_response) + cube_dict = cube_response.get("value", cube_response) return cube_dict, expected_value - @pytest.fixture(params=[ - # ---filtered case--- - (CR.CAT_X_CAT_FILT, 0.254), - # ---unfiltered case--- - (CR.CAT_X_CAT, 1.0), - ]) + @pytest.fixture( + params=[ + # ---filtered case--- + (CR.CAT_X_CAT_FILT, 0.254), + # ---unfiltered case--- + (CR.CAT_X_CAT, 1.0), + ] + ) def pop_frac_fixture(self, request): cube_dict, expected_value = request.param return cube_dict, expected_value - @pytest.fixture(params=[ - # ---weighted case--- - (CR.CAT_X_CAT_WGTD, '_WeightedCountMeasure'), - # ---unweighted case--- - (CR.CAT_X_CAT, '_UnweightedCountMeasure'), - ]) + @pytest.fixture( + params=[ + # ---weighted case--- + (CR.CAT_X_CAT_WGTD, "_WeightedCountMeasure"), + # ---unweighted case--- + (CR.CAT_X_CAT, "_UnweightedCountMeasure"), + ] + ) def wgtd_counts_fixture(self, request): cube_dict, expected_type_name = request.param return cube_dict, expected_type_name - @pytest.fixture(params=[ - # ---weighted case--- - (CR.CAT_X_CAT_WGTD, 999.557), - # ---unweighted case--- - (CR.CAT_X_CAT, 20.0), - ]) + @pytest.fixture( + params=[ + # ---weighted case--- + (CR.CAT_X_CAT_WGTD, 999.557), + # ---unweighted case--- + (CR.CAT_X_CAT, 20.0), + ] + ) def wgtd_n_fixture(self, request): cube_dict, expected_type = request.param return cube_dict, expected_type class DescribeIntegrated_MeanMeasure(object): - def it_provides_access_to_its_raw_cube_array(self): cube_dict = CR.CAT_X_CAT_MEAN_WGTD cube = CrunchCube(cube_dict) @@ -202,19 +213,20 @@ def it_provides_access_to_its_raw_cube_array(self): np.testing.assert_array_almost_equal( raw_cube_array, - [[52.78205128, 49.90697674, np.nan, np.nan, np.nan], - [50.43654822, 48.20100503, np.nan, np.nan, np.nan], - [51.56435644, 47.60283688, np.nan, np.nan, np.nan], - [58.0, 29.0, np.nan, np.nan, np.nan], - [37.53846154, 39.45238095, np.nan, np.nan, np.nan], - [36.66666667, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan]] + [ + [52.78205128, 49.90697674, np.nan, np.nan, np.nan], + [50.43654822, 48.20100503, np.nan, np.nan, np.nan], + [51.56435644, 47.60283688, np.nan, np.nan, np.nan], + [58.0, 29.0, np.nan, np.nan, np.nan], + [37.53846154, 39.45238095, np.nan, np.nan, np.nan], + [36.66666667, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], ) class DescribeIntegrated_UnweightedCountMeasure(object): - def it_provides_access_to_its_raw_cube_array(self): cube_dict = CR.CAT_X_CAT cube = CrunchCube(cube_dict) @@ -223,15 +235,11 @@ def it_provides_access_to_its_raw_cube_array(self): raw_cube_array = measure.raw_cube_array np.testing.assert_array_almost_equal( - raw_cube_array, - [[5, 3, 2, 0], - [5, 2, 3, 0], - [0, 0, 0, 0]] + raw_cube_array, [[5, 3, 2, 0], [5, 2, 3, 0], [0, 0, 0, 0]] ) class DescribeIntegrated_WeightedCountMeasure(object): - def it_provides_access_to_its_raw_cube_array(self): cube_dict = CR.CAT_X_CAT_WGTD cube = CrunchCube(cube_dict) @@ -241,16 +249,17 @@ def it_provides_access_to_its_raw_cube_array(self): np.testing.assert_array_almost_equal( raw_cube_array, - [[32.9, 87.6, 176.2, 117.5, 72.1, 13.4, 0.0, 0.0, 0.0], - [38.8, 94.1, 199.0128, 102.9, 38.8305, 26.2135, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] + [ + [32.9, 87.6, 176.2, 117.5, 72.1, 13.4, 0.0, 0.0, 0.0], + [38.8, 94.1, 199.0128, 102.9, 38.8305, 26.2135, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], ) class TestCrunchCube(TestCase): - def test_crunch_cube_loads_data(self): cube = CrunchCube(CR.CAT_X_CAT) cube_dict = cube._cube_dict @@ -282,31 +291,21 @@ def test_as_array_text(self): def test_as_array_cat_x_cat_exclude_missing(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [5, 2], - [5, 3], - ]) + expected = np.array([[5, 2], [5, 3]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) def test_as_array_cat_x_cat_unweighted(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [5, 2], - [5, 3], - ]) + expected = np.array([[5, 2], [5, 3]]) actual = cube._as_array() np.testing.assert_array_equal(actual, expected) def test_as_array_cat_x_datetime_exclude_missing(self): cube = CrunchCube(CR.CAT_X_DATETIME) - expected = np.array([ - [0, 0, 1, 0], - [0, 0, 0, 1], - [0, 1, 0, 0], - [1, 0, 0, 0], - [0, 0, 0, 0], - ]) + expected = np.array( + [[0, 0, 1, 0], [0, 0, 0, 1], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0]] + ) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) @@ -390,72 +389,63 @@ def test_proportions_datetime(self): def test_proportions_text(self): cube = CrunchCube(CR.SIMPLE_TEXT) - expected = np.array([ - 0.1666667, 0.1666667, 0.1666667, 0.1666667, 0.1666667, 0.1666667] + expected = np.array( + [0.1666667, 0.1666667, 0.1666667, 0.1666667, 0.1666667, 0.1666667] ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_cat_axis_none(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [0.3333333, 0.1333333], - [0.3333333, 0.2000000], - ]) + expected = np.array([[0.3333333, 0.1333333], [0.3333333, 0.2000000]]) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_datetime_axis_none(self): cube = CrunchCube(CR.CAT_X_DATETIME) - expected = np.array([ - [0., 0., 0.25, 0.], - [0., 0., 0., 0.25], - [0., 0.25, 0., 0.], - [0.25, 0., 0., 0.], - [0., 0., 0., 0.], - ]) + expected = np.array( + [ + [0.0, 0.0, 0.25, 0.0], + [0.0, 0.0, 0.0, 0.25], + [0.0, 0.25, 0.0, 0.0], + [0.25, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0], + ] + ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_cat_axis_0(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [0.5, 0.4], - [0.5, 0.6], - ]) + expected = np.array([[0.5, 0.4], [0.5, 0.6]]) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_datetime_axis_0(self): cube = CrunchCube(CR.CAT_X_DATETIME) - expected = np.array([ - [0, 0, 1, 0], - [0, 0, 0, 1], - [0, 1, 0, 0], - [1, 0, 0, 0], - [0, 0, 0, 0], - ]) + expected = np.array( + [[0, 0, 1, 0], [0, 0, 0, 1], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0]] + ) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_cat_axis_1(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [0.7142857, 0.2857143], - [0.6250000, 0.3750000], - ]) + expected = np.array([[0.7142857, 0.2857143], [0.6250000, 0.3750000]]) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_datetime_axis_1(self): cube = CrunchCube(CR.CAT_X_DATETIME) - expected = np.array([ - [0, 0, 1, 0], - [0, 0, 0, 1], - [0, 1, 0, 0], - [1, 0, 0, 0], - [np.nan, np.nan, np.nan, np.nan], - ]) + expected = np.array( + [ + [0, 0, 1, 0], + [0, 0, 0, 1], + [0, 1, 0, 0], + [1, 0, 0, 0], + [np.nan, np.nan, np.nan, np.nan], + ] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -473,47 +463,33 @@ def test_percentages_numeric(self): def test_percentages_datetime(self): cube = CrunchCube(CR.SIMPLE_DATETIME) - expected = np.array([25., 25., 25., 25.]) + expected = np.array([25.0, 25.0, 25.0, 25.0]) actual = cube.percentages() np.testing.assert_almost_equal(actual, expected) def test_percentages_text(self): cube = CrunchCube(CR.SIMPLE_TEXT) - expected = np.array([ - 16.6666667, - 16.6666667, - 16.6666667, - 16.6666667, - 16.6666667, - 16.6666667, - ]) + expected = np.array( + [16.6666667, 16.6666667, 16.6666667, 16.6666667, 16.6666667, 16.6666667] + ) actual = cube.percentages() np.testing.assert_almost_equal(actual, expected) def test_percentages_cat_x_cat_axis_none(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [33.3333333, 13.3333333], - [33.3333333, 20.], - ]) + expected = np.array([[33.3333333, 13.3333333], [33.3333333, 20.0]]) actual = cube.percentages() np.testing.assert_almost_equal(actual, expected) def test_percentages_cat_x_cat_axis_0(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [50, 40], - [50, 60], - ]) + expected = np.array([[50, 40], [50, 60]]) actual = cube.percentages(axis=0) np.testing.assert_almost_equal(actual, expected) def test_percentages_cat_x_cat_axis_1(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [71.4285714, 28.5714286], - [62.50000, 37.50000], - ]) + expected = np.array([[71.4285714, 28.5714286], [62.50000, 37.50000]]) actual = cube.percentages(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -537,55 +513,54 @@ def test_population_counts_datetime(self): def test_population_counts_text(self): cube = CrunchCube(CR.SIMPLE_TEXT) - expected = np.array([ - 1500.1666667, - 1500.1666667, - 1500.1666667, - 1500.1666667, - 1500.1666667, - 1500.1666667, - ]) + expected = np.array( + [ + 1500.1666667, + 1500.1666667, + 1500.1666667, + 1500.1666667, + 1500.1666667, + 1500.1666667, + ] + ) actual = cube.population_counts(9001) np.testing.assert_almost_equal(actual, expected) def test_population_counts_cat_x_cat(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [3000.3333333, 1200.1333333], - [3000.3333333, 1800.2], - ]) + expected = np.array([[3000.3333333, 1200.1333333], [3000.3333333, 1800.2]]) actual = cube.population_counts(9001) np.testing.assert_almost_equal(actual, expected) def test_filtered_population_counts(self): cube = CrunchCube(CR.CAT_X_CAT_FILT) - expected = np.array([ - [300000., 1400000., 0., 0., 0., 0.], - [5900000., 13200000., 0., 0., 0., 0.], - [600000., 2900000., 0., 0., 0., 0.], - [100000., 100000., 0., 0., 0., 0.], - [300000., 600000., 0., 0., 0., 0.]]) + expected = np.array( + [ + [300000.0, 1400000.0, 0.0, 0.0, 0.0, 0.0], + [5900000.0, 13200000.0, 0.0, 0.0, 0.0, 0.0], + [600000.0, 2900000.0, 0.0, 0.0, 0.0, 0.0], + [100000.0, 100000.0, 0.0, 0.0, 0.0, 0.0], + [300000.0, 600000.0, 0.0, 0.0, 0.0, 0.0], + ] + ) actual = cube.population_counts(100000000) np.testing.assert_almost_equal(actual, expected) def test_labels_cat_x_cat_exclude_missing(self): cube = CrunchCube(CR.CAT_X_CAT) - expected = [ - ['B', 'C'], - ['C', 'E'], - ] + expected = [["B", "C"], ["C", "E"]] actual = cube.labels() self.assertEqual(actual, expected) def test_labels_cat_x_datetime_exclude_missing(self): cube = CrunchCube(CR.CAT_X_DATETIME) expected = [ - ['red', 'green', 'blue', '4', '9'], + ["red", "green", "blue", "4", "9"], [ - '1776-07-04T00:00:00', - '1950-12-24T00:00:00', - '2000-01-01T00:00:00', - '2000-01-02T00:00:00' + "1776-07-04T00:00:00", + "1950-12-24T00:00:00", + "2000-01-01T00:00:00", + "2000-01-02T00:00:00", ], ] actual = cube.labels() @@ -593,83 +568,42 @@ def test_labels_cat_x_datetime_exclude_missing(self): def test_labels_simple_cat_array_exclude_missing(self): cube = CrunchCube(CR.SIMPLE_CAT_ARRAY) - expected = [ - ['ca_subvar_1', 'ca_subvar_2', 'ca_subvar_3'], - ['a', 'b', 'c', 'd'], - ] + expected = [["ca_subvar_1", "ca_subvar_2", "ca_subvar_3"], ["a", "b", "c", "d"]] actual = cube.labels() self.assertEqual(actual, expected) def test_as_array_simple_cat_array_exclude_missing(self): cube = CrunchCube(CR.SIMPLE_CAT_ARRAY) - expected = np.array([ - [3, 3, 0, 0], - [1, 3, 2, 0], - [0, 2, 1, 3], - ]) + expected = np.array([[3, 3, 0, 0], [1, 3, 2, 0], [0, 2, 1, 3]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) def test_as_array_cat_x_num_x_datetime(self): - '''Test 3D cube, slicing accross first (numerical) variable.''' + """Test 3D cube, slicing accross first (numerical) variable.""" cube = CrunchCube(CR.CAT_X_NUM_X_DATETIME) - expected = np.array([ - [[1, 1], - [0, 0], - [0, 0], - [0, 0]], - - [[2, 1], - [1, 1], - [0, 0], - [0, 0]], - - [[0, 0], - [2, 3], - [0, 0], - [0, 0]], - - [[0, 0], - [0, 0], - [3, 2], - [0, 0]], - - [[0, 0], - [0, 0], - [1, 1], - [0, 1]] - ]) + expected = np.array( + [ + [[1, 1], [0, 0], [0, 0], [0, 0]], + [[2, 1], [1, 1], [0, 0], [0, 0]], + [[0, 0], [2, 3], [0, 0], [0, 0]], + [[0, 0], [0, 0], [3, 2], [0, 0]], + [[0, 0], [0, 0], [1, 1], [0, 1]], + ] + ) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) def test_proportions_cat_x_num_datetime(self): cube = CrunchCube(CR.CAT_X_NUM_X_DATETIME) - expected = np.array([ - [[0.5, 0.5], - [0., 0.], - [0., 0.], - [0., 0.]], - - [[0.4, 0.2], - [0.2, 0.2], - [0., 0.], - [0., 0.]], - - [[0., 0.], - [0.4, 0.6], - [0., 0.], - [0., 0.]], - - [[0., 0.], - [0., 0.], - [0.6, 0.4], - [0., 0.]], - - [[0., 0.], - [0., 0.], - [0.33333333, 0.33333333], - [0., 0.33333333]], - ]) + expected = np.array( + [ + [[0.5, 0.5], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], + [[0.4, 0.2], [0.2, 0.2], [0.0, 0.0], [0.0, 0.0]], + [[0.0, 0.0], [0.4, 0.6], [0.0, 0.0], [0.0, 0.0]], + [[0.0, 0.0], [0.0, 0.0], [0.6, 0.4], [0.0, 0.0]], + [[0.0, 0.0], [0.0, 0.0], [0.33333333, 0.33333333], [0.0, 0.33333333]], + ] + ) # Set axis to tuple (1, 2), since we want to do a total for each slice # of the 3D cube. This is consistent with how the np.sum works # (axis parameter), which is used internally in @@ -689,75 +623,67 @@ def test_margin_cat_x_num_x_datetime_axis_0(self): cube = CrunchCube(CR.CAT_X_NUM_X_DATETIME) # Expect resulting margin to have an additional dimension # (tabs CAT, with only a single element) - expected = np.array([[ - [3, 2], - [3, 4], - [4, 3], - [0, 1], - ]]) + expected = np.array([[[3, 2], [3, 4], [4, 3], [0, 1]]]) actual = cube.margin(axis=0) np.testing.assert_array_equal(actual, expected) def test_margin_cat_x_num_x_datetime_axis_1(self): cube = CrunchCube(CR.CAT_X_NUM_X_DATETIME) - expected = np.array([ - [1, 1], - [3, 2], - [2, 3], - [3, 2], - [1, 2], - ]) + expected = np.array([[1, 1], [3, 2], [2, 3], [3, 2], [1, 2]]) actual = cube.margin(axis=1) np.testing.assert_array_equal(actual, expected) def test_margin_cat_x_num_x_datetime_axis_2(self): cube = CrunchCube(CR.CAT_X_NUM_X_DATETIME) - expected = np.array([ - [2, 0, 0, 0], - [3, 2, 0, 0], - [0, 5, 0, 0], - [0, 0, 5, 0], - [0, 0, 2, 1], - ]) + expected = np.array( + [[2, 0, 0, 0], [3, 2, 0, 0], [0, 5, 0, 0], [0, 0, 5, 0], [0, 0, 2, 1]] + ) actual = cube.margin(axis=2) np.testing.assert_array_equal(actual, expected) def test_as_array_unweighted_gender_x_ideology(self): cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([ - [32, 85, 171, 114, 70, 13], - [40, 97, 205, 106, 40, 27] - ]) + expected = np.array([[32, 85, 171, 114, 70, 13], [40, 97, 205, 106, 40, 27]]) actual = cube.as_array(weighted=False) np.testing.assert_array_equal(actual, expected) def test_as_array_weighted_gender_x_ideology(self): cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([ - [ - 32.98969072, - 87.62886598, - 176.28865979, - 117.5257732, - 72.16494845, - 13.40206186 - ], + expected = np.array( [ - 38.83495146, - 94.17475728, - 199.02912621, - 102.91262136, - 38.83495146, - 26.21359223 + [ + 32.98969072, + 87.62886598, + 176.28865979, + 117.5257732, + 72.16494845, + 13.40206186, + ], + [ + 38.83495146, + 94.17475728, + 199.02912621, + 102.91262136, + 38.83495146, + 26.21359223, + ], ] - ]) + ) actual = cube.as_array() np.testing.assert_almost_equal(actual, expected) def test_margin_weighted_gender_x_ideology_axis_0(self): cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([71.82464218, 181.80362326, 375.31778601, - 220.43839456, 110.99989991, 39.61565409]) + expected = np.array( + [ + 71.82464218, + 181.80362326, + 375.31778601, + 220.43839456, + 110.99989991, + 39.61565409, + ] + ) actual = cube.margin(axis=0) np.testing.assert_almost_equal(actual, expected) @@ -780,53 +706,57 @@ def test_margin_weighted_gender_x_ideology_axis_1(self): np.testing.assert_almost_equal(actual, expected) def test_calculate_standard_error_axis_0(self): - '''Calculate standard error across columns.''' + """Calculate standard error across columns.""" cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([ - [ - -0.715899626017458, - -0.536708837208206, - -1.485149675785275, - 1.114743776586886, - 3.355236023985286, - -2.077040949965248 - ], + expected = np.array( [ - 0.715899626017462, - 0.536708837208211, - 1.485149675785279, - -1.114743776586884, - -3.355236023985284, - 2.07704094996525 + [ + -0.715899626017458, + -0.536708837208206, + -1.485149675785275, + 1.114743776586886, + 3.355236023985286, + -2.077040949965248, + ], + [ + 0.715899626017462, + 0.536708837208211, + 1.485149675785279, + -1.114743776586884, + -3.355236023985284, + 2.07704094996525, + ], ] - ]) + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_pvals(self): cube = CrunchCube(CR.CAT_X_CAT_GERMAN_WEIGHTED) - expected = np.array([ - [ - 0.1427612835278633, - 0.0002121209149277, - 0.0001314694879104, - 0.1241771485531613, - 0.0097454103240531, - 0.0000000000000699, - 0.8033849539190183, - 0.4271118723152929 - ], + expected = np.array( [ - 0.1427612835278667, - 0.0002121209149277, - 0.0001314694879104, - 0.1241771485531642, - 0.0097454103240533, - 0.0000000000000699, - 0.8033849539190183, - 0.4271118723152956 + [ + 0.1427612835278633, + 0.0002121209149277, + 0.0001314694879104, + 0.1241771485531613, + 0.0097454103240531, + 0.0000000000000699, + 0.8033849539190183, + 0.4271118723152929, + ], + [ + 0.1427612835278667, + 0.0002121209149277, + 0.0001314694879104, + 0.1241771485531642, + 0.0097454103240533, + 0.0000000000000699, + 0.8033849539190183, + 0.4271118723152956, + ], ] - ]) + ) # Test without pruning actual = cube.pvals() np.testing.assert_almost_equal(actual, expected) @@ -841,24 +771,26 @@ def test_pvals(self): def test_pvals_stats(self): cube = CrunchCube(CR.STATS_TEST) - expected = np.array([ - [ - 0.0436818197570077, - 0.0002697141695955, - 0.0913940671748992, - 0.6836420776424197, - 0.4681291494279529, - 0.0000013632752629 - ], + expected = np.array( [ - 0.0436818197570077, - 0.0002697141695955, - 0.0913940671748992, - 0.6836420776424197, - 0.4681291494279529, - 0.0000013632752629 + [ + 0.0436818197570077, + 0.0002697141695955, + 0.0913940671748992, + 0.6836420776424197, + 0.4681291494279529, + 0.0000013632752629, + ], + [ + 0.0436818197570077, + 0.0002697141695955, + 0.0913940671748992, + 0.6836420776424197, + 0.4681291494279529, + 0.0000013632752629, + ], ] - ]) + ) # Test without pruning actual = cube.pvals() np.testing.assert_almost_equal(actual, expected) @@ -873,13 +805,15 @@ def test_pvals_stats(self): def test_mean_age_for_blame_x_gender(self): cube = CrunchCube(CR.ECON_MEAN_AGE_BLAME_X_GENDER) - expected = np.array([ - [52.78205128205122, 49.9069767441861], - [50.43654822335009, 48.20100502512572], - [51.5643564356436, 47.602836879432715], - [58, 29], - [37.53846153846155, 39.45238095238095], - ]) + expected = np.array( + [ + [52.78205128205122, 49.9069767441861], + [50.43654822335009, 48.20100502512572], + [51.5643564356436, 47.602836879432715], + [58, 29], + [37.53846153846155, 39.45238095238095], + ] + ) actual = cube.as_array() np.testing.assert_almost_equal(actual, expected) @@ -894,24 +828,26 @@ def test_z_scores_admit_by_dept_unweighted_rows(self): https://github.com/Crunch-io/whaam/blob/master/base/stats/tests/zvalues-spec.js#L42 """ cube = CrunchCube(CR.ADMIT_X_DEPT_UNWEIGHTED) - expected = np.array([ - [ - 18.04029230689576, - 13.018394979149804, - -2.576739836814013, - -3.059526328377408, - -7.230244530709987, - -19.321410263144653 - ], + expected = np.array( [ - -18.040292306895765, - -13.018394979149804, - 2.576739836814013, - 3.059526328377408, - 7.230244530709987, - 19.321410263144653 + [ + 18.04029230689576, + 13.018394979149804, + -2.576739836814013, + -3.059526328377408, + -7.230244530709987, + -19.321410263144653, + ], + [ + -18.040292306895765, + -13.018394979149804, + 2.576739836814013, + 3.059526328377408, + 7.230244530709987, + 19.321410263144653, + ], ] - ]) + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) @@ -920,107 +856,123 @@ def test_z_scores_admit_by_gender_weighted_rows(self): https://github.com/Crunch-io/whaam/blob/master/base/stats/tests/zvalues-spec.js#L67 """ cube = CrunchCube(CR.ADMIT_X_GENDER_WEIGHTED) - expected = np.array([ - [9.42561984520692, -9.425619845206922], - [-9.425619845206922, 9.42561984520692] - ]) + expected = np.array( + [ + [9.42561984520692, -9.425619845206922], + [-9.425619845206922, 9.42561984520692], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_dim_names(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = ['Statements agreed with about Climate', 'Gender'] + expected = ["Statements agreed with about Climate", "Gender"] actual = [dim.name for dim in cube.dimensions] self.assertEqual(actual, expected) def test_selected_crosstab_as_array(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [9928.20954289002, 11524.821237084192], - [9588.843313998908, 9801.254016136965], - [11697.435357575358, 13095.670425525452], - [9782.8995547749, 10531.918128023966], - [4417.596222134318, 3448.380316269752], - [6179.175512581436, 6490.427474934746], - ]) + expected = np.array( + [ + [9928.20954289002, 11524.821237084192], + [9588.843313998908, 9801.254016136965], + [11697.435357575358, 13095.670425525452], + [9782.8995547749, 10531.918128023966], + [4417.596222134318, 3448.380316269752], + [6179.175512581436, 6490.427474934746], + ] + ) actual = cube.as_array() np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_margin_by_rows(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - 21453.03077997421, - 19390.097330135875, - 24793.105783100807, - 20314.817682798865, - 7865.976538404069, - 12669.602987516182, - ]) + expected = np.array( + [ + 21453.03077997421, + 19390.097330135875, + 24793.105783100807, + 20314.817682798865, + 7865.976538404069, + 12669.602987516182, + ] + ) actual = cube.margin(axis=1) np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_margin_by_cols(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [14566.261567907562, 15607.301233922663], - [14456.513325488017, 15450.609903833058], - [14415.136475733132, 15405.898678070093], - [11485.661204663904, 11912.588886491172], - [11664.69933815247, 12110.196347286023], - [11547.413553551738, 11961.575582997419], - ]) + expected = np.array( + [ + [14566.261567907562, 15607.301233922663], + [14456.513325488017, 15450.609903833058], + [14415.136475733132, 15405.898678070093], + [11485.661204663904, 11912.588886491172], + [11664.69933815247, 12110.196347286023], + [11547.413553551738, 11961.575582997419], + ] + ) actual = cube.margin(axis=0) np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_margin_total(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - 30173.5628018302, - 29907.1232293211, - 29821.0351538032, - 23398.2500911551, - 23774.8956854385, - 23508.9891365492 - ]) + expected = np.array( + [ + 30173.5628018302, + 29907.1232293211, + 29821.0351538032, + 23398.2500911551, + 23774.8956854385, + 23508.9891365492, + ] + ) actual = cube.margin() np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_proportions_by_rows(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [0.4627882020361299, 0.5372117979638701], - [0.4945227014975337, 0.5054772985024663], - [0.47180193800279874, 0.5281980619972013], - [0.481564723224583, 0.5184352767754171], - [0.5616081106479636, 0.4383918893520365], - [0.48771658580541166, 0.5122834141945883], - ]) + expected = np.array( + [ + [0.4627882020361299, 0.5372117979638701], + [0.4945227014975337, 0.5054772985024663], + [0.47180193800279874, 0.5281980619972013], + [0.481564723224583, 0.5184352767754171], + [0.5616081106479636, 0.4383918893520365], + [0.48771658580541166, 0.5122834141945883], + ] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_proportions_by_cols(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [0.6815894041587091, 0.7384249886863752], - [0.6632887957217867, 0.6343603312193796], - [0.8114689290154947, 0.8500426167391849], - [0.8517489224566737, 0.8840998567462627], - [0.3787149667617584, 0.28475015741941767], - [0.535113381358101, 0.5426064007955989], - ]) + expected = np.array( + [ + [0.6815894041587091, 0.7384249886863752], + [0.6632887957217867, 0.6343603312193796], + [0.8114689290154947, 0.8500426167391849], + [0.8517489224566737, 0.8840998567462627], + [0.3787149667617584, 0.28475015741941767], + [0.535113381358101, 0.5426064007955989], + ] + ) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_selected_crosstab_proportions_by_cell(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [0.329036700375595, 0.381950958618156], - [0.320620717695708, 0.327723062528721], - [0.392254504152701, 0.439142047148397], - [0.418103897371069, 0.450115632023491], - [0.185809278853744, 0.14504292098248], - [0.262843097025161, 0.27608279697761], - ]) + expected = np.array( + [ + [0.329036700375595, 0.381950958618156], + [0.320620717695708, 0.327723062528721], + [0.392254504152701, 0.439142047148397], + [0.418103897371069, 0.450115632023491], + [0.185809278853744, 0.14504292098248], + [0.262843097025161, 0.27608279697761], + ] + ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) @@ -1037,51 +989,49 @@ def test_pets_x_pets_is_double_mr(self): def test_pets_x_pets_as_array(self): cube = CrunchCube(CR.PETS_X_PETS) - expected = np.array([ - [40, 14, 18], - [14, 34, 16], - [18, 16, 38], - ]) + expected = np.array([[40, 14, 18], [14, 34, 16], [18, 16, 38]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) def test_pets_x_pets_proportions_by_cell(self): cube = CrunchCube(CR.PETS_X_PETS) - expected = np.array([ - [.5, .2, .2571429], - [.2, .4303797, .2285714], - [.2571429, .2285714, .5428571], - ]) + expected = np.array( + [ + [0.5, 0.2, 0.2571429], + [0.2, 0.4303797, 0.2285714], + [0.2571429, 0.2285714, 0.5428571], + ] + ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) def test_pets_x_pets_proportions_by_col(self): cube = CrunchCube(CR.PETS_X_PETS) - expected = np.array([ - [1., .4827586, .4736842], - [.4117647, 1., 0.4210526], - [.5294118, .5517241, 1.], - ]) + expected = np.array( + [ + [1.0, 0.4827586, 0.4736842], + [0.4117647, 1.0, 0.4210526], + [0.5294118, 0.5517241, 1.0], + ] + ) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_pets_x_pets_proportions_by_row(self): cube = CrunchCube(CR.PETS_X_PETS) - expected = np.array([ - [1., .4117647, .5294118], - [.4827586, 1., .5517241], - [.4736842, .4210526, 1.], - ]) + expected = np.array( + [ + [1.0, 0.4117647, 0.5294118], + [0.4827586, 1.0, 0.5517241], + [0.4736842, 0.4210526, 1.0], + ] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_pets_x_fruit_as_array(self): cube = CrunchCube(CR.PETS_X_FRUIT) - expected = np.array([ - [12, 28], - [12, 22], - [12, 26], - ]) + expected = np.array([[12, 28], [12, 22], [12, 26]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) @@ -1093,21 +1043,15 @@ def test_pets_x_fruit_margin_row(self): def test_pets_array_as_array(self): cube = CrunchCube(CR.PETS_ARRAY) - expected = np.array([ - [45, 34], - [40, 40], - [32, 38], - ]) + expected = np.array([[45, 34], [40, 40], [32, 38]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) def test_pets_array_proportions(self): cube = CrunchCube(CR.PETS_ARRAY) - expected = np.array([ - [0.5696203, 0.4303797], - [0.5000000, 0.500000], - [0.4571429, 0.5428571], - ]) + expected = np.array( + [[0.5696203, 0.4303797], [0.5000000, 0.500000], [0.4571429, 0.5428571]] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -1133,7 +1077,7 @@ def test_pets_array_margin_by_row(self): np.testing.assert_array_equal(actual, expected) def test_pets_array_margin_by_col_not_allowed_across_items(self): - '''Colum direction is not allowed across items dimension.''' + """Colum direction is not allowed across items dimension.""" cube = CrunchCube(CR.PETS_ARRAY) with self.assertRaises(ValueError): cube.margin(axis=0) @@ -1152,123 +1096,87 @@ def test_count_weighted(self): def test_econ_x_ideology_index_by_col(self): cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([ - [ - .91861761, - .96399471, - .9394101, - 1.06629132, - 1.30027051, - .67660435, - ], + expected = np.array( [ - 1.08138239, - 1.03600529, - 1.0605899, - .93370868, - .69972949, - 1.32339565, - ], - ]) + [0.91861761, 0.96399471, 0.9394101, 1.06629132, 1.30027051, 0.67660435], + [1.08138239, 1.03600529, 1.0605899, 0.93370868, 0.69972949, 1.32339565], + ] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_econ_x_ideology_index_by_row(self): cube = CrunchCube(CR.ECON_GENDER_X_IDEOLOGY_WEIGHTED) - expected = np.array([ - [ - .91861761, - .96399471, - .9394101, - 1.06629132, - 1.30027051, - .67660435, - ], + expected = np.array( [ - 1.08138239, - 1.03600529, - 1.0605899, - .93370868, - .69972949, - 1.32339565, - ], - ]) + [0.91861761, 0.96399471, 0.9394101, 1.06629132, 1.30027051, 0.67660435], + [1.08138239, 1.03600529, 1.0605899, 0.93370868, 0.69972949, 1.32339565], + ] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_fruit_x_pets_proportions_by_cell(self): cube = CrunchCube(CR.FRUIT_X_PETS) - expected = np.array([ - [0.15, 0.15189873, 0.17142857], - [0.35, 0.27848101, 0.37142857], - ]) + expected = np.array( + [[0.15, 0.15189873, 0.17142857], [0.35, 0.27848101, 0.37142857]] + ) actual = cube.proportions(axis=None) np.testing.assert_almost_equal(actual, expected) def test_fruit_x_pets_proportions_by_row(self): cube = CrunchCube(CR.FRUIT_X_PETS) - expected = np.array([ - [.4285714, .48, .5217391], - [.5384615, .4074074, .5531915], - ]) + expected = np.array( + [[0.4285714, 0.48, 0.5217391], [0.5384615, 0.4074074, 0.5531915]] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_fruit_x_pets_proportions_by_col(self): cube = CrunchCube(CR.FRUIT_X_PETS) - expected = np.array([ - [.3, .3529412, .3157895], - [.7, .6470588, .6842105], - ]) + expected = np.array([[0.3, 0.3529412, 0.3157895], [0.7, 0.6470588, 0.6842105]]) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_pets_x_fruit_proportions_by_cell(self): cube = CrunchCube(CR.PETS_X_FRUIT) - expected = np.array([ - [0.15, 0.35], - [0.15189873, 0.27848101], - [0.17142857, 0.37142857], - ]) + expected = np.array( + [[0.15, 0.35], [0.15189873, 0.27848101], [0.17142857, 0.37142857]] + ) actual = cube.proportions(axis=None) np.testing.assert_almost_equal(actual, expected) def test_pets_x_fruit_proportions_by_col(self): cube = CrunchCube(CR.PETS_X_FRUIT) - expected = np.array([ - [.4285714, .5384615], - [.48, .4074074], - [.5217391, .5531915], - ]) + expected = np.array( + [[0.4285714, 0.5384615], [0.48, 0.4074074], [0.5217391, 0.5531915]] + ) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_pets_x_fruit_proportions_by_row(self): cube = CrunchCube(CR.PETS_X_FRUIT) - expected = np.array([ - [.3, .7], - [.3529412, .6470588], - [.3157895, .6842105], - ]) + expected = np.array( + [[0.3, 0.7], [0.3529412, 0.6470588], [0.3157895, 0.6842105]] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_cat_x_cat_array_proportions_by_row(self): - '''Get the proportions for each slice of the 3D cube. + """Get the proportions for each slice of the 3D cube. The axis is equal to 2, since this is the dimensions across which we have to calculate the margin. - ''' + """ cube = CrunchCube(CR.FRUIT_X_PETS_ARRAY) - expected = ([ - [[0.52, 0.48], - [0.57142857, 0.42857143], - [0.47826087, 0.52173913]], - - [[0.59259259, 0.40740741], - [0.46153846, 0.53846154], - [0.44680851, 0.55319149]], - ]) + expected = [ + [[0.52, 0.48], [0.57142857, 0.42857143], [0.47826087, 0.52173913]], + [ + [0.59259259, 0.40740741], + [0.46153846, 0.53846154], + [0.44680851, 0.55319149], + ], + ] actual = cube.proportions(axis=2) np.testing.assert_almost_equal(actual, expected) @@ -1291,30 +1199,27 @@ def test_ca_with_single_cat(self): def test_pets_array_x_pets_by_col(self): cube = CrunchCube(CR.PETS_ARRAY_X_PETS) - expected = np.array([ - [0.59097127, 0., 0.55956679], - [0.40902873, 1., 0.44043321], - ]) + expected = np.array( + [[0.59097127, 0.0, 0.55956679], [0.40902873, 1.0, 0.44043321]] + ) # Since cube is 3D, col dim is 1 (instead of 0) actual = cube.proportions(axis=1)[0] np.testing.assert_almost_equal(actual, expected) def test_pets_array_x_pets_row(self): cube = CrunchCube(CR.PETS_ARRAY_X_PETS) - expected = np.array([ - [0.44836533, 0., 0.48261546], - [0.39084967, 1., 0.47843137], - ]) + expected = np.array( + [[0.44836533, 0.0, 0.48261546], [0.39084967, 1.0, 0.47843137]] + ) # Since cube is 3D, row dim is 2 (instead of 0) actual = cube.proportions(axis=2)[0] np.testing.assert_almost_equal(actual, expected) def test_pets_array_x_pets_cell(self): cube = CrunchCube(CR.PETS_ARRAY_X_PETS) - expected = np.array([ - [0.24992768, 0.00000000, 0.26901938], - [0.17298235, 0.44258027, 0.21174429], - ]) + expected = np.array( + [[0.24992768, 0.00000000, 0.26901938], [0.17298235, 0.44258027, 0.21174429]] + ) actual = cube.proportions(axis=None)[0] np.testing.assert_almost_equal(actual, expected) @@ -1328,17 +1233,19 @@ def test_pets_x_pets_array_margin_by_cell(self): cube.margin() def test_pets_x_pets_array_percentages(self): - '''All directions need to return same percentages. + """All directions need to return same percentages. The only direction that makes sense is across categories, and this is handled automatically by the cube. - ''' + """ cube = CrunchCube(CR.PETS_X_PETS_ARRAY) - expected = np.array([ - [0.58823529, 0.41176471], - [0.00000000, 1.00000000], - [0.47058824, 0.52941176], - ]) + expected = np.array( + [ + [0.58823529, 0.41176471], + [0.00000000, 1.00000000], + [0.47058824, 0.52941176], + ] + ) # TODO: Remove this if not needed anymore... # TODO: Consult with jon and Mike. The new expectation is closer to what # whaam displays, but diverges from R. @@ -1371,29 +1278,25 @@ def test_profiles_percentages_add_up_to_100(self): def test_cat_x_cat_as_array_prune_cols(self): cube = CrunchCube(CR.CAT_X_CAT_WITH_EMPTY_COLS) - expected = np.array([ - [2, 2, 0, 1], - [0, 0, 0, 0], - [0, 1, 0, 2], - [0, 2, 0, 0], - [0, 2, 0, 1], - [0, 1, 0, 0], - ]) + expected = np.array( + [ + [2, 2, 0, 1], + [0, 0, 0, 0], + [0, 1, 0, 2], + [0, 2, 0, 0], + [0, 2, 0, 1], + [0, 1, 0, 0], + ] + ) actual = cube.as_array(prune=False) - expected = np.array([ - [2, 2, 1], - [0, 1, 2], - [0, 2, 0], - [0, 2, 1], - [0, 1, 0], - ]) + expected = np.array([[2, 2, 1], [0, 1, 2], [0, 2, 0], [0, 2, 1], [0, 1, 0]]) table = cube.as_array(prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] np.testing.assert_array_equal(actual, expected) pruned_expected = [ np.array([False, True, False, False, False, False]), - np.array([False, False, True, False]) + np.array([False, False, True, False]), ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1402,29 +1305,33 @@ def test_cat_x_cat_as_array_prune_cols(self): def test_cat_x_cat_props_by_col_prune_cols(self): cube = CrunchCube(CR.CAT_X_CAT_WITH_EMPTY_COLS) - expected = np.array([ - [1., 0.25, np.nan, 0.25], - [0., 0., np.nan, 0.], - [0., 0.125, np.nan, 0.5], - [0., 0.25, np.nan, 0.], - [0., 0.25, np.nan, 0.25], - [0., 0.125, np.nan, 0.] - ]) + expected = np.array( + [ + [1.0, 0.25, np.nan, 0.25], + [0.0, 0.0, np.nan, 0.0], + [0.0, 0.125, np.nan, 0.5], + [0.0, 0.25, np.nan, 0.0], + [0.0, 0.25, np.nan, 0.25], + [0.0, 0.125, np.nan, 0.0], + ] + ) actual = cube.proportions(axis=0, prune=False) - expected = np.array([ - [1., 0.25, 0.25], - [0., 0.125, 0.5], - [0., 0.25, 0.], - [0., 0.25, 0.25], - [0., 0.125, 0.] - ]) + expected = np.array( + [ + [1.0, 0.25, 0.25], + [0.0, 0.125, 0.5], + [0.0, 0.25, 0.0], + [0.0, 0.25, 0.25], + [0.0, 0.125, 0.0], + ] + ) table = cube.proportions(axis=0, prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] np.testing.assert_array_equal(actual, expected) pruned_expected = [ np.array([False, True, False, False, False, False]), - np.array([False, False, True, False]) + np.array([False, False, True, False]), ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1433,29 +1340,33 @@ def test_cat_x_cat_props_by_col_prune_cols(self): def test_cat_x_cat_props_by_row_prune_cols(self): cube = CrunchCube(CR.CAT_X_CAT_WITH_EMPTY_COLS) - expected = np.array([ - [0.4, 0.4, 0., 0.2], - [np.nan, np.nan, np.nan, np.nan], - [0., 0.33333333, 0., 0.66666667], - [0., 1., 0., 0.], - [0., 0.66666667, 0., 0.33333333], - [0., 1., 0., 0.], - ]) + expected = np.array( + [ + [0.4, 0.4, 0.0, 0.2], + [np.nan, np.nan, np.nan, np.nan], + [0.0, 0.33333333, 0.0, 0.66666667], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.66666667, 0.0, 0.33333333], + [0.0, 1.0, 0.0, 0.0], + ] + ) actual = cube.proportions(axis=1, prune=False) - expected = np.array([ - [0.4, 0.4, 0.2], - [0., 0.33333333, 0.66666667], - [0., 1., 0.], - [0., 0.66666667, 0.33333333], - [0., 1., 0.] - ]) + expected = np.array( + [ + [0.4, 0.4, 0.2], + [0.0, 0.33333333, 0.66666667], + [0.0, 1.0, 0.0], + [0.0, 0.66666667, 0.33333333], + [0.0, 1.0, 0.0], + ] + ) table = cube.proportions(axis=1, prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] np.testing.assert_almost_equal(actual, expected) pruned_expected = [ np.array([False, True, False, False, False, False]), - np.array([False, False, True, False]) + np.array([False, False, True, False]), ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1464,29 +1375,33 @@ def test_cat_x_cat_props_by_row_prune_cols(self): def test_cat_x_cat_props_by_cell_prune_cols(self): cube = CrunchCube(CR.CAT_X_CAT_WITH_EMPTY_COLS) - expected = np.array([ - [0.14285714, 0.14285714, 0., 0.07142857], - [0., 0., 0., 0.], - [0., 0.07142857, 0., 0.14285714], - [0., 0.14285714, 0., 0.], - [0., 0.14285714, 0., 0.07142857], - [0., 0.07142857, 0., 0.], - ]) + expected = np.array( + [ + [0.14285714, 0.14285714, 0.0, 0.07142857], + [0.0, 0.0, 0.0, 0.0], + [0.0, 0.07142857, 0.0, 0.14285714], + [0.0, 0.14285714, 0.0, 0.0], + [0.0, 0.14285714, 0.0, 0.07142857], + [0.0, 0.07142857, 0.0, 0.0], + ] + ) actual = cube.proportions(axis=None, prune=False) - expected = np.array([ - [0.14285714, 0.14285714, 0.07142857], - [0., 0.07142857, 0.14285714], - [0., 0.14285714, 0.], - [0., 0.14285714, 0.07142857], - [0., 0.07142857, 0.], - ]) + expected = np.array( + [ + [0.14285714, 0.14285714, 0.07142857], + [0.0, 0.07142857, 0.14285714], + [0.0, 0.14285714, 0.0], + [0.0, 0.14285714, 0.07142857], + [0.0, 0.07142857, 0.0], + ] + ) table = cube.proportions(axis=None, prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] np.testing.assert_almost_equal(actual, expected) pruned_expected = [ np.array([False, True, False, False, False, False]), - np.array([False, False, True, False]) + np.array([False, False, True, False]), ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1495,25 +1410,29 @@ def test_cat_x_cat_props_by_cell_prune_cols(self): def test_cat_x_cat_index_by_col_prune_cols(self): cube = CrunchCube(CR.CAT_X_CAT_WITH_EMPTY_COLS) - expected = np.array([ - [2.8, 0.7, np.nan, 0.7], - [np.nan, np.nan, np.nan, np.nan], - [0., 0.58333333, np.nan, 2.33333333], - [0., 1.75, np.nan, 0.], - [0., 1.16666667, np.nan, 1.16666667], - [0., 1.75, np.nan, 0.] - ]) + expected = np.array( + [ + [2.8, 0.7, np.nan, 0.7], + [np.nan, np.nan, np.nan, np.nan], + [0.0, 0.58333333, np.nan, 2.33333333], + [0.0, 1.75, np.nan, 0.0], + [0.0, 1.16666667, np.nan, 1.16666667], + [0.0, 1.75, np.nan, 0.0], + ] + ) actual = Index.data(cube, weighted=True, prune=False) # Assert index without pruning np.testing.assert_almost_equal(actual, expected) - expected = np.array([ - [2.8, 0.7, 0.7], - [0., 0.58333333, 2.33333333], - [0., 1.75, 0.], - [0., 1.16666667, 1.16666667], - [0., 1.75, 0.] - ]) + expected = np.array( + [ + [2.8, 0.7, 0.7], + [0.0, 0.58333333, 2.33333333], + [0.0, 1.75, 0.0], + [0.0, 1.16666667, 1.16666667], + [0.0, 1.75, 0.0], + ] + ) table = Index.data(cube, weighted=True, prune=True) # Assert index witih pruning actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] @@ -1521,7 +1440,7 @@ def test_cat_x_cat_index_by_col_prune_cols(self): pruned_expected = [ np.array([False, True, False, False, False, False]), - np.array([False, False, True, False]) + np.array([False, False, True, False]), ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1530,18 +1449,35 @@ def test_cat_x_cat_index_by_col_prune_cols(self): def test_prune_univariate_cat(self): cube = CrunchCube(CR.BINNED) - expected = np.array([ - 118504.40402204, - 155261.2723631, - 182923.95470245, - ]) + expected = np.array([118504.40402204, 155261.2723631, 182923.95470245]) actual = cube.as_array(prune=True) np.testing.assert_almost_equal(actual[~actual.mask], expected) pruned_expected = [ - np.array([False, True, True, True, True, True, True, True, True, - True, False, True, True, True, True, True, True, True, - True, False]) + np.array( + [ + False, + True, + True, + True, + True, + True, + True, + True, + True, + True, + False, + True, + True, + True, + True, + True, + True, + True, + True, + False, + ] + ) ] pruned = cube._prune_indices() self.assertEqual(len(pruned), len(pruned_expected)) @@ -1557,17 +1493,40 @@ def test_single_col_margin_not_iterable(self): def test_3d_percentages_by_col(self): # ---CAT x CAT x CAT--- cube = CrunchCube(CR.GENDER_PARTY_RACE) - expected = np.array([ - [[.17647059, 0., 0., 0., 0., 0., 0., 0.], - [.17647059, .05882353, 0., 0., 0., 0., 0., 0.], - [.23529412, 0., 0., 0., 0., 0.05882353, 0., 0.], - [.11764706, .05882353, 0., 0.05882353, 0., 0.05882353, 0., 0.]], - - [[.04761905, 0., 0., 0.04761905, 0., 0., 0., 0.], - [.14285714, .04761905, .0952381, .04761905, 0., .04761905, 0., 0.], - [.23809524, 0., 0.04761905, 0., 0., 0., 0., 0.], - [.19047619, 0., 0.04761905, 0., 0., 0., 0., 0.]] - ]) + expected = np.array( + [ + [ + [0.17647059, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.17647059, 0.05882353, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.23529412, 0.0, 0.0, 0.0, 0.0, 0.05882353, 0.0, 0.0], + [ + 0.11764706, + 0.05882353, + 0.0, + 0.05882353, + 0.0, + 0.05882353, + 0.0, + 0.0, + ], + ], + [ + [0.04761905, 0.0, 0.0, 0.04761905, 0.0, 0.0, 0.0, 0.0], + [ + 0.14285714, + 0.04761905, + 0.0952381, + 0.04761905, + 0.0, + 0.04761905, + 0.0, + 0.0, + ], + [0.23809524, 0.0, 0.04761905, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.19047619, 0.0, 0.04761905, 0.0, 0.0, 0.0, 0.0, 0.0], + ], + ] + ) # Set axis to tuple (1, 2), since we want to do a total for each slice # of the 3D cube. This is consistent with how the np.sum works # (axis parameter), which is used internally in @@ -1583,23 +1542,55 @@ def test_mr_dim_ind_for_cat_cube(self): self.assertEqual(actual, expected) def test_total_unweighted_margin_when_has_means(self): - '''Tests that total margin is Unweighted N, when cube has means.''' + """Tests that total margin is Unweighted N, when cube has means.""" cube = CrunchCube(CR.CAT_MEAN_WGTD) expected = 17615 actual = cube.margin(weighted=False) assert actual == expected def test_row_unweighted_margin_when_has_means(self): - '''Tests that total margin is Unweighted N, when cube has means.''' + """Tests that total margin is Unweighted N, when cube has means.""" cube = CrunchCube(CR.CAT_MEAN_WGTD) - expected = np.array([ - 806, 14, 14, 28, 780, 42, 1114, 28, 24, 746, 2, 12, 6, 2178, 2026, - 571, 136, 16, 14, 1334, 1950, 26, 128, 4, 28, 3520, 1082, 36, 56, - 556, 38, 146, 114, 28, 12, - ]) - actual = np.ma.compressed( - cube.margin(axis=1, weighted=False, prune=True) + expected = np.array( + [ + 806, + 14, + 14, + 28, + 780, + 42, + 1114, + 28, + 24, + 746, + 2, + 12, + 6, + 2178, + 2026, + 571, + 136, + 16, + 14, + 1334, + 1950, + 26, + 128, + 4, + 28, + 3520, + 1082, + 36, + 56, + 556, + 38, + 146, + 114, + 28, + 12, + ] ) + actual = np.ma.compressed(cube.margin(axis=1, weighted=False, prune=True)) np.testing.assert_array_equal(actual, expected) # not testing cube._prune_indices() because the margin has 6367 cells @@ -1622,7 +1613,7 @@ def test_ca_x_single_cat_counts(self): expecteds = [ (np.array([False, False]), np.array([False])), (np.array([False, False]), np.array([False])), - (np.array([False, False],), np.array([False])), + (np.array([False, False]), np.array([False])), ] actuals = cube._prune_indices() for expected, actual in zip(expecteds, actuals): @@ -1631,33 +1622,25 @@ def test_ca_x_single_cat_counts(self): def test_ca_x_single_cat_props_by_col(self): cube = CrunchCube(CR.CA_X_SINGLE_CAT) - expected = np.array([ - [0.52, 0.48], - [0.57142857, 0.42857143], - [0.47826087, 0.52173913], - ]) + expected = np.array( + [[0.52, 0.48], [0.57142857, 0.42857143], [0.47826087, 0.52173913]] + ) # Col direction is 1 (and not 0) because of 3D cube. actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_ca_x_single_cat_props_by_row(self): cube = CrunchCube(CR.CA_X_SINGLE_CAT) - expected = np.array([ - [1., 1.], - [1., 1.], - [1., 1.], - ]) + expected = np.array([[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]) # Col direction is 2 (and not 1) because of 3D cube. actual = cube.proportions(axis=2) np.testing.assert_almost_equal(actual, expected) def test_ca_x_single_cat_props_by_cell(self): cube = CrunchCube(CR.CA_X_SINGLE_CAT) - expected = np.array([ - [0.52, 0.48], - [0.57142857, 0.42857143], - [0.47826087, 0.52173913], - ]) + expected = np.array( + [[0.52, 0.48], [0.57142857, 0.42857143], [0.47826087, 0.52173913]] + ) # Col direction is (1, 2) because 3D cube (total per slice). actual = cube.proportions(axis=(1, 2)) np.testing.assert_almost_equal(actual, expected) @@ -1689,11 +1672,7 @@ def test_ca_x_single_cat_cell_margins(self): def test_ca_subvar_x_cat_hs_counts_prune(self): cube = CrunchCube(CR.CA_SUBVAR_X_CAT_HS) - expected = np.array([ - [3, 3, 0, 0, 6], - [1, 3, 2, 0, 4], - [0, 2, 1, 3, 2], - ]) + expected = np.array([[3, 3, 0, 0, 6], [1, 3, 2, 0, 4], [0, 2, 1, 3, 2]]) actual = cube.as_array(include_transforms_for_dims=[0, 1], prune=True) np.testing.assert_array_equal(actual, expected) @@ -1705,14 +1684,13 @@ def test_means_univariate_cat(self): def test_means_bivariate_cat(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = [[np.array([ - 2.19444444, - 2.19230769, - 2.26666667, - 1.88990826, - 1.76363636, - 3.85, - ])]] + expected = [ + [ + np.array( + [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] + ) + ] + ] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -1763,10 +1741,7 @@ def test_means_cat_x_cat_arr_pets_first(self): expected = [ [np.array([1.48, 1.40740741]), np.array([1.71111111, 1.64705882])], [np.array([1.42857143, 1.53846154]), np.array([1.6, 1.7])], - [ - np.array([1.52173913, 1.55319149]), - np.array([1.65625, 1.68421053]), - ], + [np.array([1.52173913, 1.55319149]), np.array([1.65625, 1.68421053])], ] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -1775,68 +1750,262 @@ def test_means_with_null_values(self): cube = CrunchCube(CR.SCALE_WITH_NULL_VALUES) scale_means = cube.scale_means() assert_scale_means_equal( - scale_means, - [[np.array([1.2060688, 1.0669344, 1.023199]), None]] + scale_means, [[np.array([1.2060688, 1.0669344, 1.023199]), None]] ) def test_values_services(self): cube = CrunchCube(CR.MR_X_CA_CAT_X_CA_SUBVAR) # Axis is 1, which is 'col' direction, since 3D cube. actual = cube.proportions(axis=1)[0] - expected = np.array([ - [0.14285714, 0.10204082, 0.20512821, 0.16363636, 0.16438356, 0.1372549, 0.18181818, 0.2991453, 0.32, 0.44776119], # noqa - [0.07142857, 0.23469388, 0.17948718, 0.14545455, 0.20547945, 0.09803922, 0.27272727, 0.11111111, 0.352, 0.23880597], # noqa - [0.12857143, 0.19387755, 0.1025641, 0.16363636, 0.1369863, 0.15686275, 0.25, 0.17094017, 0.136, 0.14925373], # noqa - [0.15714286, 0.15306122, 0.14102564, 0.05454545, 0.17808219, 0.09803922, 0.18181818, 0.20512821, 0.064, 0.05223881], # noqa - [0.12857143, 0.12244898, 0.1025641, 0.05454545, 0.15068493, 0.07843137, 0.06060606, 0.1025641, 0.064, 0.05970149], # noqa - [0.05714286, 0.09183673, 0.20512821, 0.09090909, 0.09589041, 0.11764706, 0.03030303, 0.02564103, 0.032, 0.01492537], # noqa - [0.08571429, 0.04081633, 0.05128205, 0.07272727, 0.01369863, 0.11764706, 0.01515152, 0.05128205, 0.024, 0.02238806], # noqa - [0.17142857, 0.04081633, 0.01282051, 0.03636364, 0.02739726, 0.01960784, 0.00757576, 0.00854701, 0.008, 0.00746269], # noqa - [0.01428571, 0.02040816, 0., 0.14545455, 0.01369863, 0.11764706, 0., 0., 0., 0.00746269], # noqa - [0.04285714, 0., 0., 0.07272727, 0.01369863, 0.05882353, 0., 0.02564103, 0., 0.], # noqa - [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], - ]) + expected = np.array( + [ + [ + 0.14285714, + 0.10204082, + 0.20512821, + 0.16363636, + 0.16438356, + 0.1372549, + 0.18181818, + 0.2991453, + 0.32, + 0.44776119, + ], # noqa + [ + 0.07142857, + 0.23469388, + 0.17948718, + 0.14545455, + 0.20547945, + 0.09803922, + 0.27272727, + 0.11111111, + 0.352, + 0.23880597, + ], # noqa + [ + 0.12857143, + 0.19387755, + 0.1025641, + 0.16363636, + 0.1369863, + 0.15686275, + 0.25, + 0.17094017, + 0.136, + 0.14925373, + ], # noqa + [ + 0.15714286, + 0.15306122, + 0.14102564, + 0.05454545, + 0.17808219, + 0.09803922, + 0.18181818, + 0.20512821, + 0.064, + 0.05223881, + ], # noqa + [ + 0.12857143, + 0.12244898, + 0.1025641, + 0.05454545, + 0.15068493, + 0.07843137, + 0.06060606, + 0.1025641, + 0.064, + 0.05970149, + ], # noqa + [ + 0.05714286, + 0.09183673, + 0.20512821, + 0.09090909, + 0.09589041, + 0.11764706, + 0.03030303, + 0.02564103, + 0.032, + 0.01492537, + ], # noqa + [ + 0.08571429, + 0.04081633, + 0.05128205, + 0.07272727, + 0.01369863, + 0.11764706, + 0.01515152, + 0.05128205, + 0.024, + 0.02238806, + ], # noqa + [ + 0.17142857, + 0.04081633, + 0.01282051, + 0.03636364, + 0.02739726, + 0.01960784, + 0.00757576, + 0.00854701, + 0.008, + 0.00746269, + ], # noqa + [ + 0.01428571, + 0.02040816, + 0.0, + 0.14545455, + 0.01369863, + 0.11764706, + 0.0, + 0.0, + 0.0, + 0.00746269, + ], # noqa + [ + 0.04285714, + 0.0, + 0.0, + 0.07272727, + 0.01369863, + 0.05882353, + 0.0, + 0.02564103, + 0.0, + 0.0, + ], # noqa + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ] + ) np.testing.assert_almost_equal(actual, expected) np.testing.assert_almost_equal(actual, expected) def test_mr_props_with_hs_by_cell(self): cube = CrunchCube(CR.LETTERS_X_PETS_HS) - expected = np.array([ - [0.10769231, 0.16923077, 0.27692308, 0.26153846, 0.15384615, 0.15384615], # noqa - [0.11111111, 0.20634921, 0.31746032, 0.19047619, 0.15873016, 0.15873016], # noqa - [0.09090909, 0.22727273, 0.31818182, 0.24242424, 0.12121212, 0.12121212], # noqa - [0.10447761, 0.14925373, 0.25373134, 0.13432836, 0.17910448, 0.17910448], # noqa - [0.07462687, 0.11940299, 0.19402985, 0.23880597, 0.1641791, 0.1641791], # noqa - ]) + expected = np.array( + [ + [ + 0.10769231, + 0.16923077, + 0.27692308, + 0.26153846, + 0.15384615, + 0.15384615, + ], # noqa + [ + 0.11111111, + 0.20634921, + 0.31746032, + 0.19047619, + 0.15873016, + 0.15873016, + ], # noqa + [ + 0.09090909, + 0.22727273, + 0.31818182, + 0.24242424, + 0.12121212, + 0.12121212, + ], # noqa + [ + 0.10447761, + 0.14925373, + 0.25373134, + 0.13432836, + 0.17910448, + 0.17910448, + ], # noqa + [ + 0.07462687, + 0.11940299, + 0.19402985, + 0.23880597, + 0.1641791, + 0.1641791, + ], # noqa + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_mr_props_with_hs_by_row(self): cube = CrunchCube(CR.LETTERS_X_PETS_HS) - expected = np.array([ - [0.15555556, 0.24444444, 0.4, 0.37777778, 0.22222222, 0.22222222], - [0.16666667, 0.30952381, 0.47619048, 0.28571429, 0.23809524, 0.23809524], # noqa - [0.13333333, 0.33333333, 0.46666667, 0.35555556, 0.17777778, 0.17777778], # noqa - [0.18421053, 0.26315789, 0.44736842, 0.23684211, 0.31578947, 0.31578947], # noqa - [0.125, 0.2, 0.325, 0.4, 0.275, 0.275], - ]) + expected = np.array( + [ + [0.15555556, 0.24444444, 0.4, 0.37777778, 0.22222222, 0.22222222], + [ + 0.16666667, + 0.30952381, + 0.47619048, + 0.28571429, + 0.23809524, + 0.23809524, + ], # noqa + [ + 0.13333333, + 0.33333333, + 0.46666667, + 0.35555556, + 0.17777778, + 0.17777778, + ], # noqa + [ + 0.18421053, + 0.26315789, + 0.44736842, + 0.23684211, + 0.31578947, + 0.31578947, + ], # noqa + [0.125, 0.2, 0.325, 0.4, 0.275, 0.275], + ] + ) actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_mr_props_with_hs_by_col(self): cube = CrunchCube(CR.LETTERS_X_PETS_HS) - expected = np.array([ - [0.53846154, 0.6875, 0.62068966, 0.94444444, 0.55555556, 0.55555556], # noqa - [0.58333333, 0.68421053, 0.64516129, 0.66666667, 0.71428571, 0.71428571], # noqa - [0.5, 0.78947368, 0.67741935, 0.76190476, 0.57142857, 0.57142857], - [0.53846154, 0.58823529, 0.56666667, 0.5, 0.63157895, 0.63157895], - [0.45454545, 0.47058824, 0.46428571, 0.76190476, 0.61111111, 0.61111111], # noqa - ]) + expected = np.array( + [ + [ + 0.53846154, + 0.6875, + 0.62068966, + 0.94444444, + 0.55555556, + 0.55555556, + ], # noqa + [ + 0.58333333, + 0.68421053, + 0.64516129, + 0.66666667, + 0.71428571, + 0.71428571, + ], # noqa + [0.5, 0.78947368, 0.67741935, 0.76190476, 0.57142857, 0.57142857], + [0.53846154, 0.58823529, 0.56666667, 0.5, 0.63157895, 0.63157895], + [ + 0.45454545, + 0.47058824, + 0.46428571, + 0.76190476, + 0.61111111, + 0.61111111, + ], # noqa + ] + ) actual = cube.proportions(axis=0, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_3d_pruning_indices(self): - '''Test pruning indices for a simple XYZ cube.''' + """Test pruning indices for a simple XYZ cube.""" cube = CrunchCube(CR.XYZ_SIMPLE_ALLTYPES) # Zeroth slice of the XYZ array: @@ -1865,11 +2034,7 @@ def test_3d_pruning_indices(self): def test_mr_x_ca_rows_margin(self): cube = CrunchCube(CR.MR_X_CA_HS) actual = cube.margin(axis=2) - expected = np.array([ - [3, 3, 3], - [4, 4, 4], - [0, 0, 0], - ]) + expected = np.array([[3, 3, 3], [4, 4, 4], [0, 0, 0]]) np.testing.assert_array_equal(actual, expected) def test_ca_x_mr_margin(self): @@ -1885,27 +2050,25 @@ def test_ca_x_mr_margin_prune(self): cube = CrunchCube(CR.CA_X_MR_WEIGHTED_HS) margin = cube.margin( - axis=1, weighted=False, include_transforms_for_dims=[0, 1, 2], - prune=True, + axis=1, weighted=False, include_transforms_for_dims=[0, 1, 2], prune=True )[0] - np.testing.assert_array_equal( - margin, - np.array([504, 215, 224, 76, 8, 439]) - ) + np.testing.assert_array_equal(margin, np.array([504, 215, 224, 76, 8, 439])) def test_mr_x_cat_x_mr_pruning(self): cube = CrunchCube(CR.MR_X_CAT_X_MR_PRUNE) - expected = np.array([ - [False, False, False, True], - [False, False, False, True], - [True, True, True, True], - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - [True, True, True, True], - [True, True, True, True], - ]) + expected = np.array( + [ + [False, False, False, True], + [False, False, False, True], + [True, True, True, True], + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + [True, True, True, True], + [True, True, True, True], + ] + ) actual = cube.proportions(prune=True)[0].mask np.testing.assert_array_equal(actual, expected) @@ -1936,104 +2099,106 @@ def test_gender_x_weight_pruning(self): np.testing.assert_array_equal(actual, expected) def test_proportions_cat_x_mr_x_cat(self): - cube = CrunchCube(CR.CAT_X_MR_X_CAT['slides'][0]['cube']) - props = cube.proportions( - axis=1, include_transforms_for_dims=[1, 2], prune=True, - ) + cube = CrunchCube(CR.CAT_X_MR_X_CAT["slides"][0]["cube"]) + props = cube.proportions(axis=1, include_transforms_for_dims=[1, 2], prune=True) # Test first slice - expected = np.array([ - [0.3647320622384293, 0.3539601689446188], - [0.2217369551352075, 0.21179394663351137], - [0.2892943293978049, 0.2755799995757032], - [0.30472468951159837, 0.31183395927247587], - [0.1564932915102434, 0.12122561350397994], - [0.14341569357975512, 0.16573829062583212], - [0.3088773171830892, 0.30399159711003093], - [0.3531835200406305, 0.4001713397700346], - [0.2572968713520773, 0.24375187975969445], - [0.25130939319998297, 0.1977549624477041], - [0.274565755319545, 0.2997170882672239], - [0.32608867343144654, 0.344478827337916], - [0.35921238787890847, 0.3513630660099009], - [0.25634234169007164, 0.16894820580901035], - [0.22099299650777843, 0.22466833670878553], - [0.2276649518247445, 0.24565762260105783], - [0.2643381997593724, 0.1982327504994244], - [0.41491884119922506, 0.4258666971460735], - [0.4623019656879477, 0.520868963921971], - [0.35277296769118416, 0.2813894529707485], - [0.4003762375617921, 0.42681767440587187], - [0.25925087940264385, 0.2731916153395818], - [0.4753330440584336, 0.43648850969829933], - [0.28148528548474344, 0.24591762645117995], - [0.49727220036895625, 0.5108530445282087], - [0.32590772578924143, 0.359683660082846], - [0.3595152413326164, 0.4049397928654146], - [0.42108775668830034, 0.3454454870295823], - [0.4205886117048783, 0.39122538735554757], - [0.228770284468049, 0.20059146301631123], - [0.24603034757739972, 0.2735752782805667], - [0.3065494749862463, 0.32314540506421324], - [0.27194030884117687, 0.30970380251451973], - [0.2091262494207975, 0.22920517801957993], - [0.31769765653105564, 0.28958158962721786], - [0.3560762345705489, 0.3102687419303191], - [0.4804715042882989, 0.5011391743289532], - [0.3811599892254701, 0.4226226669501276], - [0.41029213392178276, 0.1884401015918774], - ]) + expected = np.array( + [ + [0.3647320622384293, 0.3539601689446188], + [0.2217369551352075, 0.21179394663351137], + [0.2892943293978049, 0.2755799995757032], + [0.30472468951159837, 0.31183395927247587], + [0.1564932915102434, 0.12122561350397994], + [0.14341569357975512, 0.16573829062583212], + [0.3088773171830892, 0.30399159711003093], + [0.3531835200406305, 0.4001713397700346], + [0.2572968713520773, 0.24375187975969445], + [0.25130939319998297, 0.1977549624477041], + [0.274565755319545, 0.2997170882672239], + [0.32608867343144654, 0.344478827337916], + [0.35921238787890847, 0.3513630660099009], + [0.25634234169007164, 0.16894820580901035], + [0.22099299650777843, 0.22466833670878553], + [0.2276649518247445, 0.24565762260105783], + [0.2643381997593724, 0.1982327504994244], + [0.41491884119922506, 0.4258666971460735], + [0.4623019656879477, 0.520868963921971], + [0.35277296769118416, 0.2813894529707485], + [0.4003762375617921, 0.42681767440587187], + [0.25925087940264385, 0.2731916153395818], + [0.4753330440584336, 0.43648850969829933], + [0.28148528548474344, 0.24591762645117995], + [0.49727220036895625, 0.5108530445282087], + [0.32590772578924143, 0.359683660082846], + [0.3595152413326164, 0.4049397928654146], + [0.42108775668830034, 0.3454454870295823], + [0.4205886117048783, 0.39122538735554757], + [0.228770284468049, 0.20059146301631123], + [0.24603034757739972, 0.2735752782805667], + [0.3065494749862463, 0.32314540506421324], + [0.27194030884117687, 0.30970380251451973], + [0.2091262494207975, 0.22920517801957993], + [0.31769765653105564, 0.28958158962721786], + [0.3560762345705489, 0.3102687419303191], + [0.4804715042882989, 0.5011391743289532], + [0.3811599892254701, 0.4226226669501276], + [0.41029213392178276, 0.1884401015918774], + ] + ) actual = compress_pruned(props[0]) np.testing.assert_almost_equal(actual, expected) # Test second slice - expected = np.array([ - [0.4031214008509537, 0.4056176483118717], - [0.24070198556407071, 0.25911741489783324], - [0.3464300357360538, 0.33912070707907394], - [0.3574620243397532, 0.37758989006965377], - [0.14907456320910992, 0.15890701660953999], - [0.20651100193920027, 0.1789634776591901], - [0.30520247457440536, 0.3270678407142803], - [0.3810285430516052, 0.3997309090998591], - [0.34271319381187965, 0.17385655771473044], - [0.3591305867483556, 0.2685531153107514], - [0.2996020578719067, 0.29215934221779744], - [0.3902291806673195, 0.39354067543725346], - [0.40337866312317217, 0.4250345472210801], - [0.32114152359818676, 0.30423847092340256], - [0.2653311867224287, 0.27833063737964403], - [0.313528046383254, 0.3000437600045656], - [0.3920027268884396, 0.36933090371694116], - [0.515781215492543, 0.4851941444303692], - [0.5427173809468948, 0.5754703450096686], - [0.3514753251895221, 0.3381463298582681], - [0.40789566838261765, 0.43525540615386243], - [0.3595684862225866, 0.38051785122829174], - [0.556336290160639, 0.47918668411102733], - [0.3006536550040242, 0.31770376362899333], - [0.5132046910093269, 0.5548090283383379], - [0.4409089206826546, 0.36616426510098665], - [0.40390891699096854, 0.3888593109712533], - [0.3914326716352874, 0.3346157095319079], - [0.4423415709934932, 0.47752483308415145], - [0.33543493750667275, 0.30087121770598385], - [0.30409560492337334, 0.33096009035672747], - [0.4028029720384424, 0.4497865293548307], - [0.37991282964691514, 0.3817002730808065], - [0.26937198075202085, 0.2530238979016483], - [0.3367641290249356, 0.3210357156509789], - [0.4376473666508847, 0.4044796591984694], - [0.5986306705327854, 0.5886692367162286], - [0.3493779725965881, 0.3533483607971598], - [0.08962504168280223, 0.4352830423033842], - ]) + expected = np.array( + [ + [0.4031214008509537, 0.4056176483118717], + [0.24070198556407071, 0.25911741489783324], + [0.3464300357360538, 0.33912070707907394], + [0.3574620243397532, 0.37758989006965377], + [0.14907456320910992, 0.15890701660953999], + [0.20651100193920027, 0.1789634776591901], + [0.30520247457440536, 0.3270678407142803], + [0.3810285430516052, 0.3997309090998591], + [0.34271319381187965, 0.17385655771473044], + [0.3591305867483556, 0.2685531153107514], + [0.2996020578719067, 0.29215934221779744], + [0.3902291806673195, 0.39354067543725346], + [0.40337866312317217, 0.4250345472210801], + [0.32114152359818676, 0.30423847092340256], + [0.2653311867224287, 0.27833063737964403], + [0.313528046383254, 0.3000437600045656], + [0.3920027268884396, 0.36933090371694116], + [0.515781215492543, 0.4851941444303692], + [0.5427173809468948, 0.5754703450096686], + [0.3514753251895221, 0.3381463298582681], + [0.40789566838261765, 0.43525540615386243], + [0.3595684862225866, 0.38051785122829174], + [0.556336290160639, 0.47918668411102733], + [0.3006536550040242, 0.31770376362899333], + [0.5132046910093269, 0.5548090283383379], + [0.4409089206826546, 0.36616426510098665], + [0.40390891699096854, 0.3888593109712533], + [0.3914326716352874, 0.3346157095319079], + [0.4423415709934932, 0.47752483308415145], + [0.33543493750667275, 0.30087121770598385], + [0.30409560492337334, 0.33096009035672747], + [0.4028029720384424, 0.4497865293548307], + [0.37991282964691514, 0.3817002730808065], + [0.26937198075202085, 0.2530238979016483], + [0.3367641290249356, 0.3210357156509789], + [0.4376473666508847, 0.4044796591984694], + [0.5986306705327854, 0.5886692367162286], + [0.3493779725965881, 0.3533483607971598], + [0.08962504168280223, 0.4352830423033842], + ] + ) actual = compress_pruned(props[1]) np.testing.assert_almost_equal(actual, expected) def test_univ_mr_with_hs_does_not_crash(self): """Assert that MR with H&S doesn't crash.""" - cube = CrunchCube(CR.UNIV_MR_WITH_HS['slides'][0]['cube']) + cube = CrunchCube(CR.UNIV_MR_WITH_HS["slides"][0]["cube"]) cube.as_array(include_transforms_for_dims=[0]) # If it doesn't crash, the test passes, we don't actually care about # the result. We only care that the H&S transform doesn't crash the MR diff --git a/tests/integration/test_cube_slice.py b/tests/integration/test_cube_slice.py index 39a8585f2..95be92758 100644 --- a/tests/integration/test_cube_slice.py +++ b/tests/integration/test_cube_slice.py @@ -10,7 +10,6 @@ class DescribeIntegratedCubeSlice(object): - def it_provides_a_console_friendly_repr_for_a_slice(self): cube = CrunchCube(CR.CAT_X_CAT) slice_ = cube.slices[0] @@ -33,26 +32,28 @@ def it_knows_zscore_for_MR_X_MR_X_CAT(self): np.testing.assert_array_almost_equal( zscore, - np.array([ - [-2.0890161, 2.0890161], - [-0.31167807, 0.31167807], - [-0.4574511, 0.4574511], - [0.08713899, -0.08713899], - [-1.88534457, 1.88534457], - [-1.18201963, 1.18201963], - [-0.14570511, 0.14570511], - [-0.79331024, 0.79331024], - [-0.10870154, 0.10870154], - [0.39665764, -0.39665764], - [-0.76214626, 0.76214626], - [-1.59164242, 1.59164242], - [np.nan, np.nan], - [-1.97343777, 1.97343777], - [-0.63278752, 0.63278752], - [-0.4446455, 0.4446455], - [-0.10084772, 0.10084772], - [-0.42861964, 0.42861964], - ]) + np.array( + [ + [-2.0890161, 2.0890161], + [-0.31167807, 0.31167807], + [-0.4574511, 0.4574511], + [0.08713899, -0.08713899], + [-1.88534457, 1.88534457], + [-1.18201963, 1.18201963], + [-0.14570511, 0.14570511], + [-0.79331024, 0.79331024], + [-0.10870154, 0.10870154], + [0.39665764, -0.39665764], + [-0.76214626, 0.76214626], + [-1.59164242, 1.59164242], + [np.nan, np.nan], + [-1.97343777, 1.97343777], + [-0.63278752, 0.63278752], + [-0.4446455, 0.4446455], + [-0.10084772, 0.10084772], + [-0.42861964, 0.42861964], + ] + ), ) def test_mr_x_mr_single_cat_pruning(self): @@ -69,17 +70,16 @@ def test_mr_single_cat_x_mr_margin_with_pruning(self): class DescribeCubeSliceAPI(object): - def it_calculates_correct_index_tables_for_single_elements(self): cs = CrunchCube(CR.MR_X_CAT_BOTH_SINGLE_ELEMENT).slices[0] # Check for column direction (as in the exporter), backed by R - expected = np.array([[0., 110.39006714]]) + expected = np.array([[0.0, 110.39006714]]) index_table = cs.index_table(axis=0) np.testing.assert_array_almost_equal(index_table, expected) # Check for row direction, backed by R - expected = np.array([[0., 116.472612]]) + expected = np.array([[0.0, 116.472612]]) index_table = cs.index_table(axis=1) np.testing.assert_array_almost_equal(index_table, expected) @@ -90,12 +90,19 @@ def test_labels_with_hs_and_pruning(): # Withouut pruning or H&S expected = [ [ - u'Married', u'Separated', u'Divorced', u'Widowed', u'Single', - u'Domestic partnership', + u"Married", + u"Separated", + u"Divorced", + u"Widowed", + u"Single", + u"Domestic partnership", ], [ - u'President Obama', u'Republicans in Congress', u'Both', - u'Neither', u'Not sure', + u"President Obama", + u"Republicans in Congress", + u"Both", + u"Neither", + u"Not sure", ], ] actual = cs.labels() @@ -103,14 +110,8 @@ def test_labels_with_hs_and_pruning(): # Apply pruning expected = [ - [ - u'Married', u'Separated', u'Divorced', u'Widowed', - u'Domestic partnership', - ], - [ - u'President Obama', u'Republicans in Congress', u'Both', - u'Not sure', - ], + [u"Married", u"Separated", u"Divorced", u"Widowed", u"Domestic partnership"], + [u"President Obama", u"Republicans in Congress", u"Both", u"Not sure"], ] actual = cs.labels(prune=True) assert actual == expected @@ -118,12 +119,21 @@ def test_labels_with_hs_and_pruning(): # Apply H&S expected = [ [ - u'Married', u'left alone', u'Separated', u'Divorced', u'Widowed', - u'Single', u'Domestic partnership', + u"Married", + u"left alone", + u"Separated", + u"Divorced", + u"Widowed", + u"Single", + u"Domestic partnership", ], [ - u'President Obama', u'Obama + Republicans', - u'Republicans in Congress', u'Both', u'Neither', u'Not sure', + u"President Obama", + u"Obama + Republicans", + u"Republicans in Congress", + u"Both", + u"Neither", + u"Not sure", ], ] actual = cs.labels(hs_dims=[0, 1]) @@ -132,12 +142,19 @@ def test_labels_with_hs_and_pruning(): # Apply H&S and pruning expected = [ [ - u'Married', u'left alone', u'Separated', u'Divorced', u'Widowed', - u'Domestic partnership', + u"Married", + u"left alone", + u"Separated", + u"Divorced", + u"Widowed", + u"Domestic partnership", ], [ - u'President Obama', u'Obama + Republicans', - u'Republicans in Congress', u'Both', u'Not sure', + u"President Obama", + u"Obama + Republicans", + u"Republicans in Congress", + u"Both", + u"Not sure", ], ] actual = cs.labels(prune=True, hs_dims=[0, 1]) diff --git a/tests/integration/test_dimension.py b/tests/integration/test_dimension.py index 741aee1a4..ba2d66c5d 100644 --- a/tests/integration/test_dimension.py +++ b/tests/integration/test_dimension.py @@ -15,7 +15,6 @@ class DescribeIntegratedAllDimensions(object): - def it_resolves_the_type_of_each_dimension(self, type_fixture): dimension_dicts, expected_types = type_fixture all_dimensions = AllDimensions(dimension_dicts) @@ -25,7 +24,7 @@ def it_resolves_the_type_of_each_dimension(self, type_fixture): assert dimension_types == expected_types def it_provides_access_to_the_apparent_dimensions(self): - dimension_dicts = CR.CA_X_MR_WEIGHTED_HS['result']['dimensions'] + dimension_dicts = CR.CA_X_MR_WEIGHTED_HS["result"]["dimensions"] all_dimensions = AllDimensions(dimension_dicts) apparent_dimension_types = tuple( @@ -36,18 +35,19 @@ def it_provides_access_to_the_apparent_dimensions(self): # fixtures ------------------------------------------------------- - @pytest.fixture(params=[ - (CR.CAT_X_CAT, (DT.CAT, DT.CAT)), - (CR.CA_X_MR_WEIGHTED_HS, (DT.CA, DT.CA_CAT, DT.MR, DT.MR_CAT)), - ]) + @pytest.fixture( + params=[ + (CR.CAT_X_CAT, (DT.CAT, DT.CAT)), + (CR.CA_X_MR_WEIGHTED_HS, (DT.CA, DT.CA_CAT, DT.MR, DT.MR_CAT)), + ] + ) def type_fixture(self, request): cube_response, expected_types = request.param - dimension_dicts = cube_response['result']['dimensions'] + dimension_dicts = cube_response["result"]["dimensions"] return dimension_dicts, expected_types class TestDimension(TestCase): - def test_subtotals_indices_single_subtotal(self): dimension = CrunchCube(CR.ECON_BLAME_WITH_HS).dimensions[0] hs_indices = dimension.hs_indices @@ -63,81 +63,55 @@ def test_inserted_hs_indices_single_subtotal(self): def test_labels_for_categoricals(self): dimension_dict = { - 'type': { - 'class': 'categorical', - 'categories': [ - { - 'id': 1, - 'name': 'Cat', - 'missing': False, - }, - { - 'id': 2, - 'name': 'Mouse', - 'missing': False, - }, - { - 'id': -1, - 'name': 'Iguana', - 'missing': True, - }, - ] + "type": { + "class": "categorical", + "categories": [ + {"id": 1, "name": "Cat", "missing": False}, + {"id": 2, "name": "Mouse", "missing": False}, + {"id": -1, "name": "Iguana", "missing": True}, + ], } } dimension = Dimension(dimension_dict, DT.CAT) # ---get only non-missing--- labels = dimension.labels() - assert labels == ['Cat', 'Mouse'] + assert labels == ["Cat", "Mouse"] # ---get all--- labels = dimension.labels(include_missing=True) - assert labels == ['Cat', 'Mouse', 'Iguana'] + assert labels == ["Cat", "Mouse", "Iguana"] def test_labels_for_numericals(self): dimension_dict = { - 'type': { - 'class': 'enum', - 'elements': [ - { - 'id': 0, - 'value': 'smallish', - 'missing': False - }, - { - 'id': 1, - 'value': 'kinda big', - 'missing': False - }, - { - 'id': 2, - 'value': {}, - 'missing': True - } + "type": { + "class": "enum", + "elements": [ + {"id": 0, "value": "smallish", "missing": False}, + {"id": 1, "value": "kinda big", "missing": False}, + {"id": 2, "value": {}, "missing": True}, ], - 'subtype': { - 'class': 'numeric' - } + "subtype": {"class": "numeric"}, } } dimension = Dimension(dimension_dict, DT.BINNED_NUMERIC) # ---non-missing labels--- labels = dimension.labels() - assert labels == ['smallish', 'kinda big'] + assert labels == ["smallish", "kinda big"] # ---all labels, both valid and missing--- labels = dimension.labels(include_missing=True) - assert labels == ['smallish', 'kinda big', ''] + assert labels == ["smallish", "kinda big", ""] # ---all labels, both valid and missing--- labels = dimension.labels(include_cat_ids=True) - assert labels == [('smallish', 0), ('kinda big', 1)] + assert labels == [("smallish", 0), ("kinda big", 1)] def test_subtotals_indices_two_subtotals(self): dimension = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING).dimensions[0] hs_indices = dimension.hs_indices - self.assertEqual(hs_indices, ((1, (0, 1)), ('bottom', (3, 4)))) + self.assertEqual(hs_indices, ((1, (0, 1)), ("bottom", (3, 4)))) def test_inserted_hs_indices_two_subtotals(self): dimension = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING).dimensions[0] @@ -149,84 +123,83 @@ def test_inserted_hs_indices_two_subtotals(self): def test_inserted_hs_indices_order_and_labels(self): dimension_dict = { - 'references': { - 'view': { - 'transform': { - 'insertions': [ + "references": { + "view": { + "transform": { + "insertions": [ { - 'anchor': 'bottom', - 'args': [111], - 'function': 'subtotal', - 'name': 'bottoms up one', + "anchor": "bottom", + "args": [111], + "function": "subtotal", + "name": "bottoms up one", }, { - 'anchor': 'bottom', - 'args': [222], - 'function': 'subtotal', - 'name': 'bottoms up two', + "anchor": "bottom", + "args": [222], + "function": "subtotal", + "name": "bottoms up two", }, { - 'anchor': 'bottom', - 'args': [333], - 'function': 'subtotal', - 'name': 'bottoms up three', + "anchor": "bottom", + "args": [333], + "function": "subtotal", + "name": "bottoms up three", }, { - 'anchor': 'top', - 'args': [444], - 'function': 'subtotal', - 'name': 'on top one', + "anchor": "top", + "args": [444], + "function": "subtotal", + "name": "on top one", }, { - 'anchor': 'top', - 'args': [555], - 'function': 'subtotal', - 'name': 'on top two', + "anchor": "top", + "args": [555], + "function": "subtotal", + "name": "on top two", }, { - 'anchor': 333, - 'args': [555], - 'function': 'subtotal', - 'name': 'in the middle one', + "anchor": 333, + "args": [555], + "function": "subtotal", + "name": "in the middle one", }, { - 'anchor': 333, - 'args': [555], - 'function': 'subtotal', - 'name': 'in the middle two', - } + "anchor": 333, + "args": [555], + "function": "subtotal", + "name": "in the middle two", + }, ] } } }, - 'type': { + "type": { "categories": [ - { - "id": 111, - }, - { - "id": 222, - }, - { - "id": 333, - }, - { - "id": 444, - }, - { - "id": 555, - } + {"id": 111}, + {"id": 222}, + {"id": 333}, + {"id": 444}, + {"id": 555}, ], - "class": "categorical" - } + "class": "categorical", + }, } dimension = Dimension(dimension_dict, DT.CAT) assert dimension.inserted_hs_indices == [0, 1, 5, 6, 9, 10, 11] assert dimension.labels(include_transforms=True) == [ - 'on top one', 'on top two', '', '', '', - 'in the middle one', 'in the middle two', '', '', - 'bottoms up one', 'bottoms up two', 'bottoms up three' + "on top one", + "on top two", + "", + "", + "", + "in the middle one", + "in the middle two", + "", + "", + "bottoms up one", + "bottoms up two", + "bottoms up three", ] def test_has_transforms_false(self): @@ -251,11 +224,11 @@ def test_hs_indices_with_bad_data(self): subvar_dim = cube.dimensions[0] anchor_idxs = [anchor_idx for anchor_idx, _ in subvar_dim.hs_indices] - assert anchor_idxs == ['bottom', 'bottom'] + assert anchor_idxs == ["bottom", "bottom"] cat_dim = cube.dimensions[1] anchor_idxs = [anchor_idx for anchor_idx, _ in cat_dim.hs_indices] - assert anchor_idxs == ['bottom', 'bottom'] + assert anchor_idxs == ["bottom", "bottom"] def test_skips_bad_data_for_hs_indices(self): """Test H&S indices with bad input data. @@ -265,116 +238,94 @@ def test_skips_bad_data_for_hs_indices(self): leftovers in the variables. """ dimension_dict = { - 'references': { - 'view': { - 'transform': { - 'insertions': [ + "references": { + "view": { + "transform": { + "insertions": [ + {"anchor": 101, "name": "This is respondent ideology"}, { - 'anchor': 101, - 'name': 'This is respondent ideology', + "anchor": 2, + "args": [1, 2], + "function": "subtotal", + "name": "Liberal net", }, { - 'anchor': 2, - 'args': [1, 2], - 'function': 'subtotal', - 'name': 'Liberal net', + "anchor": 5, + "args": [5, 4], + "function": "subtotal", + "name": "Conservative net", }, { - 'anchor': 5, - 'args': [5, 4], - 'function': 'subtotal', - 'name': 'Conservative net', + "anchor": "fake anchor", + "args": ["fake_arg_1", "fake_arg_2"], + "function": "fake_fcn_name_not_subtotal", + "name": "Fake Name", }, - { - 'anchor': 'fake anchor', - 'args': ['fake_arg_1', 'fake_arg_2'], - 'function': 'fake_fcn_name_not_subtotal', - 'name': 'Fake Name', - } ] } } }, - 'type': { - 'categories': [ - { - 'numeric_value': 1, - 'id': 1, - 'name': 'President Obama', - 'missing': False - }, + "type": { + "categories": [ { - 'numeric_value': 2, - 'id': 2, - 'name': 'Republicans in Congress', - 'missing': False + "numeric_value": 1, + "id": 1, + "name": "President Obama", + "missing": False, }, { - 'numeric_value': 5, - 'id': 5, - 'name': 'Not sure', - 'missing': False + "numeric_value": 2, + "id": 2, + "name": "Republicans in Congress", + "missing": False, }, - { - 'numeric_value': 4, - 'id': 4, - 'name': 'Neither', - 'missing': False - } + {"numeric_value": 5, "id": 5, "name": "Not sure", "missing": False}, + {"numeric_value": 4, "id": 4, "name": "Neither", "missing": False}, ], - 'class': 'categorical', - 'ordinal': False - } + "class": "categorical", + "ordinal": False, + }, } dimension = Dimension(dimension_dict, DT.CAT) hs_indices = dimension.hs_indices - print('hs_indices == %s' % [hs_indices]) + print("hs_indices == %s" % [hs_indices]) assert hs_indices == ((1, (0, 1)), (2, (2, 3))) def test_subtotals(self): dimension_dict = { - 'references': { - 'view': { - 'transform': { - 'insertions': [ + "references": { + "view": { + "transform": { + "insertions": [ + {"anchor": 101, "name": "This is respondent ideology"}, { - 'anchor': 101, - 'name': 'This is respondent ideology', + "anchor": 2, + "args": [1, 2], + "function": "subtotal", + "name": "Liberal net", }, { - 'anchor': 2, - 'args': [1, 2], - 'function': 'subtotal', - 'name': 'Liberal net', + "anchor": 5, + "args": [5, 4], + "function": "subtotal", + "name": "Conservative net", }, { - 'anchor': 5, - 'args': [5, 4], - 'function': 'subtotal', - 'name': 'Conservative net', + "anchor": "fake anchor", + "args": ["fake_arg_1", "fake_arg_2"], + "function": "fake_fcn_name_not_subtotal", + "name": "Fake Name", }, - { - 'anchor': 'fake anchor', - 'args': ['fake_arg_1', 'fake_arg_2'], - 'function': 'fake_fcn_name_not_subtotal', - 'name': 'Fake Name', - } ] } } }, - 'type': { - 'categories': [ - {'id': 1}, - {'id': 5}, - {'id': 8}, - {'id': 9}, - {'id': -1}, - ], - 'class': 'categorical' - } + "type": { + "categories": [{"id": 1}, {"id": 5}, {"id": 8}, {"id": 9}, {"id": -1}], + "class": "categorical", + }, } dimension = Dimension(dimension_dict, DT.CAT) @@ -384,29 +335,29 @@ def test_subtotals(self): subtotal = subtotals[0] assert isinstance(subtotal, _Subtotal) - assert subtotal.anchor == 'bottom' + assert subtotal.anchor == "bottom" assert subtotal.addend_ids == (1,) assert subtotal.addend_idxs == (0,) - assert subtotal.label == 'Liberal net' + assert subtotal.label == "Liberal net" subtotal = subtotals[1] assert isinstance(subtotal, _Subtotal) assert subtotal.anchor == 5 assert subtotal.addend_ids == (5,) assert subtotal.addend_idxs == (1,) - assert subtotal.label == 'Conservative net' + assert subtotal.label == "Conservative net" def test_numeric_values(self): dimension_dict = { - 'type': { - 'categories': [ - {'id': 42, 'missing': False, 'numeric_value': 1}, - {'id': 43, 'missing': False, 'numeric_value': 2}, - {'id': 44, 'missing': True, 'numeric_value': 3}, - {'id': 45, 'missing': False, 'numeric_value': None}, - {'id': 46, 'missing': False} + "type": { + "categories": [ + {"id": 42, "missing": False, "numeric_value": 1}, + {"id": 43, "missing": False, "numeric_value": 2}, + {"id": 44, "missing": True, "numeric_value": 3}, + {"id": 45, "missing": False, "numeric_value": None}, + {"id": 46, "missing": False}, ], - 'class': 'categorical' + "class": "categorical", } } dimension = Dimension(dimension_dict, DT.CAT) diff --git a/tests/integration/test_headers_and_subtotals.py b/tests/integration/test_headers_and_subtotals.py index 7e0a8e686..35a33ca6d 100644 --- a/tests/integration/test_headers_and_subtotals.py +++ b/tests/integration/test_headers_and_subtotals.py @@ -12,16 +12,15 @@ class TestHeadersAndSubtotals(TestCase): - def test_headings_econ_blame_one_subtotal(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS) expected = [ - 'President Obama', - 'Republicans in Congress', - 'Test New Heading (Obama and Republicans)', - 'Both', - 'Neither', - 'Not sure', + "President Obama", + "Republicans in Congress", + "Test New Heading (Obama and Republicans)", + "Both", + "Neither", + "Not sure", ] actual = cube.labels(include_transforms_for_dims=[0])[0] self.assertEqual(actual, expected) @@ -29,11 +28,11 @@ def test_headings_econ_blame_one_subtotal(self): def test_headings_econ_blame_one_subtotal_do_not_fetch(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS) expected = [ - 'President Obama', - 'Republicans in Congress', - 'Both', - 'Neither', - 'Not sure', + "President Obama", + "Republicans in Congress", + "Both", + "Neither", + "Not sure", ] actual = cube.labels(include_transforms_for_dims=None)[0] self.assertEqual(actual, expected) @@ -41,13 +40,13 @@ def test_headings_econ_blame_one_subtotal_do_not_fetch(self): def test_headings_econ_blame_two_subtotal_without_missing(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING) expected = [ - 'President Obama', - 'Republicans in Congress', - 'Test New Heading (Obama and Republicans)', - 'Both', - 'Neither', - 'Not sure', - 'Test Heading with Skipped', + "President Obama", + "Republicans in Congress", + "Test New Heading (Obama and Republicans)", + "Both", + "Neither", + "Not sure", + "Test Heading with Skipped", ] actual = cube.labels(include_transforms_for_dims=[0])[0] self.assertEqual(actual, expected) @@ -55,11 +54,11 @@ def test_headings_econ_blame_two_subtotal_without_missing(self): def test_headings_two_subtotal_without_missing_do_not_fetch(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING) expected = [ - 'President Obama', - 'Republicans in Congress', - 'Both', - 'Neither', - 'Not sure', + "President Obama", + "Republicans in Congress", + "Both", + "Neither", + "Not sure", ] actual = cube.labels(include_transforms_for_dims=None)[0] self.assertEqual(actual, expected) @@ -67,20 +66,18 @@ def test_headings_two_subtotal_without_missing_do_not_fetch(self): def test_headings_econ_blame_two_subtotal_with_missing(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING) expected = [ - 'President Obama', - 'Republicans in Congress', - 'Test New Heading (Obama and Republicans)', - 'Both', - 'Neither', - 'Not sure', - 'Skipped', - 'Not Asked', - 'No Data', - 'Test Heading with Skipped', + "President Obama", + "Republicans in Congress", + "Test New Heading (Obama and Republicans)", + "Both", + "Neither", + "Not sure", + "Skipped", + "Not Asked", + "No Data", + "Test Heading with Skipped", ] - actual = cube.labels( - include_missing=True, include_transforms_for_dims=[0], - )[0] + actual = cube.labels(include_missing=True, include_transforms_for_dims=[0])[0] self.assertEqual(actual, expected) def test_subtotals_as_array_one_transform(self): @@ -103,141 +100,158 @@ def test_subtotals_as_array_two_transforms_missing_excluded(self): def test_subtotals_proportions_one_transform(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS) - expected = np.array([ - .2858576, .3971916, .6830491, .2427282, .0060181, .0682046, - ]) + expected = np.array( + [0.2858576, 0.3971916, 0.6830491, 0.2427282, 0.0060181, 0.0682046] + ) actual = cube.proportions(include_transforms_for_dims=[0]) np.testing.assert_almost_equal(actual, expected) def test_subtotals_proportions_one_transform_do_not_fetch(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS) - expected = np.array([ - .2858576, .3971916, .2427282, .0060181, .0682046, - ]) + expected = np.array([0.2858576, 0.3971916, 0.2427282, 0.0060181, 0.0682046]) actual = cube.proportions(include_transforms_for_dims=None) np.testing.assert_almost_equal(actual, expected) def test_subtotals_proportions_two_transforms_missing_excluded(self): cube = CrunchCube(CR.ECON_BLAME_WITH_HS_MISSING) - expected = np.array([ - .2858576, - .3971916, - .6830491, - .2427282, - .0060181, - .0682046, - .0742227, - ]) + expected = np.array( + [ + 0.2858576, + 0.3971916, + 0.6830491, + 0.2427282, + 0.0060181, + 0.0682046, + 0.0742227, + ] + ) actual = cube.proportions(include_transforms_for_dims=[0]) np.testing.assert_almost_equal(actual, expected) def test_labels_on_2d_cube_with_hs_on_1st_dim(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = [[ - 'President Obama', - 'Republicans in Congress', - 'Test New Heading (Obama and Republicans)', - 'Both', - 'Neither', - 'Not sure', - ], [ - 'Very liberal', - 'Liberal', - 'Moderate', - 'Conservative', - 'Very Conservative', - 'Not sure', - ]] + expected = [ + [ + "President Obama", + "Republicans in Congress", + "Test New Heading (Obama and Republicans)", + "Both", + "Neither", + "Not sure", + ], + [ + "Very liberal", + "Liberal", + "Moderate", + "Conservative", + "Very Conservative", + "Not sure", + ], + ] actual = cube.labels(include_transforms_for_dims=[0, 1]) self.assertEqual(actual, expected) def test_labels_on_2d_cube_with_hs_on_both_dim(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) - expected = [[ - 'President Obama', - 'Republicans in Congress', - 'Test New Heading (Obama and Republicans)', - 'Both', - 'Neither', - 'Not sure', - ], [ - 'Very liberal', - 'Liberal', - 'Moderate', - 'Test 2nd dim Heading', - 'Conservative', - 'Very Conservative', - 'Not sure', - ]] + expected = [ + [ + "President Obama", + "Republicans in Congress", + "Test New Heading (Obama and Republicans)", + "Both", + "Neither", + "Not sure", + ], + [ + "Very liberal", + "Liberal", + "Moderate", + "Test 2nd dim Heading", + "Conservative", + "Very Conservative", + "Not sure", + ], + ] actual = cube.labels(include_transforms_for_dims=[0, 1]) self.assertEqual(actual, expected) def test_labels_on_2d_cube_with_hs_on_both_dim_do_not_fetch(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) - expected = [[ - 'President Obama', - 'Republicans in Congress', - 'Both', - 'Neither', - 'Not sure', - ], [ - 'Very liberal', - 'Liberal', - 'Moderate', - 'Conservative', - 'Very Conservative', - 'Not sure', - ]] + expected = [ + [ + "President Obama", + "Republicans in Congress", + "Both", + "Neither", + "Not sure", + ], + [ + "Very liberal", + "Liberal", + "Moderate", + "Conservative", + "Very Conservative", + "Not sure", + ], + ] actual = cube.labels(include_transforms_for_dims=None) self.assertEqual(actual, expected) def test_subtotals_as_array_2d_cube_with_hs_on_row(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = np.array([ - [3, 14, 80, 114, 67, 7], - [59, 132, 162, 29, 12, 2], - [62, 146, 242, 143, 79, 9], - [6, 29, 109, 67, 26, 5], - [1, 1, 1, 1, 0, 2], - [3, 6, 23, 7, 5, 24], - ]) + expected = np.array( + [ + [3, 14, 80, 114, 67, 7], + [59, 132, 162, 29, 12, 2], + [62, 146, 242, 143, 79, 9], + [6, 29, 109, 67, 26, 5], + [1, 1, 1, 1, 0, 2], + [3, 6, 23, 7, 5, 24], + ] + ) actual = cube.as_array(include_transforms_for_dims=[0, 1]) np.testing.assert_array_equal(actual, expected) def test_subtotals_as_array_2d_cube_with_hs_on_col(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_COL_HS) - expected = np.array([ - [3, 14, 80, 94, 114, 67, 7], - [59, 132, 162, 294, 29, 12, 2], - [6, 29, 109, 138, 67, 26, 5], - [1, 1, 1, 2, 1, 0, 2], - [3, 6, 23, 29, 7, 5, 24], - ]) + expected = np.array( + [ + [3, 14, 80, 94, 114, 67, 7], + [59, 132, 162, 294, 29, 12, 2], + [6, 29, 109, 138, 67, 26, 5], + [1, 1, 1, 2, 1, 0, 2], + [3, 6, 23, 29, 7, 5, 24], + ] + ) actual = cube.as_array(include_transforms_for_dims=[0, 1]) np.testing.assert_array_equal(actual, expected) def test_subtotals_as_array_2d_cube_with_hs_on_both_dim(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) - expected = np.array([ - [3, 14, 80, 94, 114, 67, 7], - [59, 132, 162, 294, 29, 12, 2], - [62, 146, 242, 388, 143, 79, 9], - [6, 29, 109, 138, 67, 26, 5], - [1, 1, 1, 2, 1, 0, 2], - [3, 6, 23, 29, 7, 5, 24], - ]) + expected = np.array( + [ + [3, 14, 80, 94, 114, 67, 7], + [59, 132, 162, 294, 29, 12, 2], + [62, 146, 242, 388, 143, 79, 9], + [6, 29, 109, 138, 67, 26, 5], + [1, 1, 1, 2, 1, 0, 2], + [3, 6, 23, 29, 7, 5, 24], + ] + ) actual = cube.as_array(include_transforms_for_dims=[0, 1]) np.testing.assert_array_equal(actual, expected) def test_subtotals_as_array_2d_cube_with_hs_on_both_dim_do_not_fetch(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) - expected = np.array([ - [3, 14, 80, 114, 67, 7], - [59, 132, 162, 29, 12, 2], - [6, 29, 109, 67, 26, 5], - [1, 1, 1, 1, 0, 2], - [3, 6, 23, 7, 5, 24], - ]) + expected = np.array( + [ + [3, 14, 80, 114, 67, 7], + [59, 132, 162, 29, 12, 2], + [6, 29, 109, 67, 26, 5], + [1, 1, 1, 1, 0, 2], + [3, 6, 23, 7, 5, 24], + ] + ) actual = cube.as_array(include_transforms_for_dims=None) np.testing.assert_array_equal(actual, expected) @@ -267,130 +281,164 @@ def test_subtotals_margin_2d_cube_with_hs_on_two_dim_by_row(self): def test_subtotals_proportions_2d_cube_with_hs_on_row_by_cell(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = np.array([ - [.00300903, .01404213, .08024072, .11434303, .0672016, .00702106], - [.05917753, .13239719, .16248746, .02908726, .01203611, .00200602], - [.06218656, .14643932, .24272818, .14343029, .07923771, .00902708], - [.00601805, .02908726, .10932798, .0672016, .02607823, .00501505], - [.00100301, .00100301, .00100301, .00100301, 0, .00200602], - [.00300903, .00601805, .02306921, .00702106, .00501505, .02407222] - ]) + expected = np.array( + [ + [0.00300903, 0.01404213, 0.08024072, 0.11434303, 0.0672016, 0.00702106], + [ + 0.05917753, + 0.13239719, + 0.16248746, + 0.02908726, + 0.01203611, + 0.00200602, + ], + [ + 0.06218656, + 0.14643932, + 0.24272818, + 0.14343029, + 0.07923771, + 0.00902708, + ], + [0.00601805, 0.02908726, 0.10932798, 0.0672016, 0.02607823, 0.00501505], + [0.00100301, 0.00100301, 0.00100301, 0.00100301, 0, 0.00200602], + [ + 0.00300903, + 0.00601805, + 0.02306921, + 0.00702106, + 0.00501505, + 0.02407222, + ], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_subtotals_proportions_2d_cube_with_hs_on_row_by_col(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = np.array([ - [.04166667, .07692308, .21333333, .52293578, .60909091, .175], - [.81944444, .72527473, .432, .13302752, .10909091, .05], - [.86111111, .8021978, .64533333, .6559633, .71818182, .225], - [.08333333, .15934066, .29066667, .30733945, .23636364, .125], - [.01388889, .00549451, .00266667, .00458716, 0, .05], - [.04166667, .03296703, .06133333, .03211009, .04545455, .6], - ]) + expected = np.array( + [ + [0.04166667, 0.07692308, 0.21333333, 0.52293578, 0.60909091, 0.175], + [0.81944444, 0.72527473, 0.432, 0.13302752, 0.10909091, 0.05], + [0.86111111, 0.8021978, 0.64533333, 0.6559633, 0.71818182, 0.225], + [0.08333333, 0.15934066, 0.29066667, 0.30733945, 0.23636364, 0.125], + [0.01388889, 0.00549451, 0.00266667, 0.00458716, 0, 0.05], + [0.04166667, 0.03296703, 0.06133333, 0.03211009, 0.04545455, 0.6], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1], axis=0) np.testing.assert_almost_equal(actual, expected) def test_subtotals_proportions_2d_cube_with_hs_on_row_by_row(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = np.array([ - [.01052632, .04912281, .28070175, .4, .23508772, .0245614], - [.1489899, .33333333, .40909091, .07323232, .03030303, .00505051], - [.09104258, .2143906, .35535977, .20998532, .11600587, .01321586], - [.02479339, .11983471, .45041322, .2768595, .10743802, .02066116], - [.16666667, .16666667, .16666667, .16666667, 0, .33333333], - [.04411765, .08823529, .33823529, .10294118, .07352941, .35294118], - ]) + expected = np.array( + [ + [0.01052632, 0.04912281, 0.28070175, 0.4, 0.23508772, 0.0245614], + [0.1489899, 0.33333333, 0.40909091, 0.07323232, 0.03030303, 0.00505051], + [0.09104258, 0.2143906, 0.35535977, 0.20998532, 0.11600587, 0.01321586], + [0.02479339, 0.11983471, 0.45041322, 0.2768595, 0.10743802, 0.02066116], + [0.16666667, 0.16666667, 0.16666667, 0.16666667, 0, 0.33333333], + [ + 0.04411765, + 0.08823529, + 0.33823529, + 0.10294118, + 0.07352941, + 0.35294118, + ], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1], axis=1) np.testing.assert_almost_equal(actual, expected) def test_subtotals_proportions_2d_cube_with_hs_on_two_dim_by_cell(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) - expected = np.array([ - [ - .00300903, - .01404213, - .08024072, - .09428285, - .11434303, - .0672016, - .00702106 - ], - [ - .05917753, - .13239719, - .16248746, - .29488465, - .02908726, - .01203611, - .00200602 - ], + expected = np.array( [ - .06218656, - .14643932, - .24272818, - .3891675, - .14343029, - .07923771, - .00902708 - ], - [ - .00601805, - .02908726, - .10932798, - .13841525, - .0672016, - .02607823, - .00501505 - ], - [ - .00100301, - .00100301, - .00100301, - .00200602, - .00100301, - 0, - .00200602 - ], - [ - .00300903, - .00601805, - .02306921, - .02908726, - .00702106, - .00501505, - .02407222 - ], - ]) + [ + 0.00300903, + 0.01404213, + 0.08024072, + 0.09428285, + 0.11434303, + 0.0672016, + 0.00702106, + ], + [ + 0.05917753, + 0.13239719, + 0.16248746, + 0.29488465, + 0.02908726, + 0.01203611, + 0.00200602, + ], + [ + 0.06218656, + 0.14643932, + 0.24272818, + 0.3891675, + 0.14343029, + 0.07923771, + 0.00902708, + ], + [ + 0.00601805, + 0.02908726, + 0.10932798, + 0.13841525, + 0.0672016, + 0.02607823, + 0.00501505, + ], + [ + 0.00100301, + 0.00100301, + 0.00100301, + 0.00200602, + 0.00100301, + 0, + 0.00200602, + ], + [ + 0.00300903, + 0.00601805, + 0.02306921, + 0.02908726, + 0.00702106, + 0.00501505, + 0.02407222, + ], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_ca_labels_with_hs(self): cube = CrunchCube(CR.SIMPLE_CA_HS) expected = [ - ['ca_subvar_1', 'ca_subvar_2', 'ca_subvar_3'], - ['a', 'b', 'Test A and B combined', 'c', 'd'] + ["ca_subvar_1", "ca_subvar_2", "ca_subvar_3"], + ["a", "b", "Test A and B combined", "c", "d"], ] actual = cube.labels(include_transforms_for_dims=[0]) self.assertEqual(actual, expected) def test_ca_as_array_with_hs(self): cube = CrunchCube(CR.SIMPLE_CA_HS) - expected = np.array([ - [3, 3, 6, 0, 0], - [1, 3, 4, 2, 0], - [0, 2, 2, 1, 3] - ]) + expected = np.array([[3, 3, 6, 0, 0], [1, 3, 4, 2, 0], [0, 2, 2, 1, 3]]) actual = cube.as_array(include_transforms_for_dims=[0, 1]) np.testing.assert_array_equal(actual, expected) def test_ca_proportions_with_hs(self): cube = CrunchCube(CR.SIMPLE_CA_HS) - expected = np.array([ - [.5, .5, 1, 0, 0], - [.16666667, .5, .66666667, .33333333, 0], - [0, .33333333, .33333333, .16666667, .5] - ]) + expected = np.array( + [ + [0.5, 0.5, 1, 0, 0], + [0.16666667, 0.5, 0.66666667, 0.33333333, 0], + [0, 0.33333333, 0.33333333, 0.16666667, 0.5], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1], axis=1) np.testing.assert_almost_equal(actual, expected) @@ -404,16 +452,16 @@ def test_hs_with_anchor_on_zero_position_labels(self): cube = CrunchCube(CR.ECON_US_PROBLEM_X_BIGGER_PROBLEM) expected = [ [ - 'Serious net', - 'Very serious', - 'Somewhat serious', - 'Not very serious', - 'Not at all serious', - 'Not sure', + "Serious net", + "Very serious", + "Somewhat serious", + "Not very serious", + "Not at all serious", + "Not sure", ], [ - 'Sexual assaults that go unreported or unpunished', - 'False accusations of sexual assault', + "Sexual assaults that go unreported or unpunished", + "False accusations of sexual assault", ], ] actual = cube.labels(include_transforms_for_dims=[0, 1]) @@ -421,64 +469,102 @@ def test_hs_with_anchor_on_zero_position_labels(self): def test_hs_with_anchor_on_zero_position_as_props_by_col(self): cube = CrunchCube(CR.ECON_US_PROBLEM_X_BIGGER_PROBLEM) - expected = np.array([ - [0.93244626, 0.66023166], - [0.63664278, 0.23166023], - [0.29580348, 0.42857143], - [0.04401228, 0.21428571], - [0.00307062, 0.06177606], - [0.02047083, 0.06370656], - ]) + expected = np.array( + [ + [0.93244626, 0.66023166], + [0.63664278, 0.23166023], + [0.29580348, 0.42857143], + [0.04401228, 0.21428571], + [0.00307062, 0.06177606], + [0.02047083, 0.06370656], + ] + ) actual = cube.proportions(axis=0, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_hs_with_anchor_on_zero_position_as_props_by_row(self): cube = CrunchCube(CR.ECON_US_PROBLEM_X_BIGGER_PROBLEM) - expected = np.array([ - [0.72705507, 0.27294493], - [0.83827493, 0.16172507], - [0.56555773, 0.43444227], - [0.27922078, 0.72077922], - [0.08571429, 0.91428571], - [0.37735849, 0.62264151], - ]) + expected = np.array( + [ + [0.72705507, 0.27294493], + [0.83827493, 0.16172507], + [0.56555773, 0.43444227], + [0.27922078, 0.72077922], + [0.08571429, 0.91428571], + [0.37735849, 0.62264151], + ] + ) actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_hs_with_anchor_on_zero_position_as_props_by_cell(self): cube = CrunchCube(CR.ECON_US_PROBLEM_X_BIGGER_PROBLEM) - expected = np.array([ - [0.60936455, 0.22876254], - [0.41605351, 0.08026756], - [0.19331104, 0.14849498], - [0.02876254, 0.07424749], - [0.00200669, 0.02140468], - [0.01337793, 0.02207358], - ]) + expected = np.array( + [ + [0.60936455, 0.22876254], + [0.41605351, 0.08026756], + [0.19331104, 0.14849498], + [0.02876254, 0.07424749], + [0.00200669, 0.02140468], + [0.01337793, 0.02207358], + ] + ) actual = cube.proportions(include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_subtotals_pvals_2d_cube_with_hs_on_row(self): """Ensure that pvals shape is the same as table shape with H%S""" cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) - expected = np.array([ - [1.92562832e-06, 5.20117283e-12, 8.30737469e-05, 0.00000000e+00, - 1.77635684e-15, 1.13223165e-01], - [2.90878432e-14, 0.00000000e+00, 8.11477145e-02, 0.00000000e+00, - 5.87376814e-11, 4.64141147e-06], - [1.05605732e-03, 3.70613426e-03, 6.11851617e-03, 1.18269053e-02, - 8.68890220e-01, 7.62914197e-02], - [3.69990005e-01, 9.19546240e-01, 2.88068221e-01, 7.57299844e-01, - 3.86924216e-01, 2.41648361e-04], - [3.53745446e-01, 3.70094812e-02, 5.03974440e-01, 1.67769523e-02, - 3.15641644e-01, 0.00000000e+00], - ]) + expected = np.array( + [ + [ + 1.92562832e-06, + 5.20117283e-12, + 8.30737469e-05, + 0.00000000e00, + 1.77635684e-15, + 1.13223165e-01, + ], + [ + 2.90878432e-14, + 0.00000000e00, + 8.11477145e-02, + 0.00000000e00, + 5.87376814e-11, + 4.64141147e-06, + ], + [ + 1.05605732e-03, + 3.70613426e-03, + 6.11851617e-03, + 1.18269053e-02, + 8.68890220e-01, + 7.62914197e-02, + ], + [ + 3.69990005e-01, + 9.19546240e-01, + 2.88068221e-01, + 7.57299844e-01, + 3.86924216e-01, + 2.41648361e-04, + ], + [ + 3.53745446e-01, + 3.70094812e-02, + 5.03974440e-01, + 1.67769523e-02, + 3.15641644e-01, + 0.00000000e00, + ], + ] + ) actual = cube.pvals() np.testing.assert_almost_equal(actual, expected) def test_fruit_hs_top_bottom_labels(self): cube = CrunchCube(CR.FRUIT_HS_TOP_BOTTOM) - expected = [['TOP', 'rambutan', 'MIDDLE', 'satsuma', 'BOTTOM']] + expected = [["TOP", "rambutan", "MIDDLE", "satsuma", "BOTTOM"]] actual = cube.labels(include_transforms_for_dims=[0]) assert actual == expected @@ -496,25 +582,23 @@ def test_fruit_hs_top_bottom_counts(self): def test_fruit_x_pets_hs_top_bottom_middle_props(self): cube = CrunchCube(CR.FRUIT_X_PETS_HS_TOP_BOTTOM) - expected = np.array([ - [1., 1., 1.], - [0.3, 0.35294118, 0.31578947], - [1., 1., 1.], - [0.7, 0.64705882, 0.68421053], - [1., 1., 1.], - ]) + expected = np.array( + [ + [1.0, 1.0, 1.0], + [0.3, 0.35294118, 0.31578947], + [1.0, 1.0, 1.0], + [0.7, 0.64705882, 0.68421053], + [1.0, 1.0, 1.0], + ] + ) actual = cube.proportions(axis=0, include_transforms_for_dims=[0]) np.testing.assert_almost_equal(actual, expected) def test_fruit_x_pets_hs_top_bottom_middle_counts(self): cube = CrunchCube(CR.FRUIT_X_PETS_HS_TOP_BOTTOM) - expected = np.array([ - [40, 34, 38], - [12, 12, 12], - [40, 34, 38], - [28, 22, 26], - [40, 34, 38], - ]) + expected = np.array( + [[40, 34, 38], [12, 12, 12], [40, 34, 38], [28, 22, 26], [40, 34, 38]] + ) actual = cube.as_array(include_transforms_for_dims=[0]) np.testing.assert_array_equal(actual, expected) @@ -538,12 +622,7 @@ def test_hs_indices_pruned_cat_x_num(self): def test_cat_x_num_counts_pruned_with_hs(self): cube = CrunchCube(CR.CAT_X_NUM_HS_PRUNE) - expected = np.array([ - [0], - [1], - [1], - [0], - ]) + expected = np.array([[0], [1], [1], [0]]) # Extract only non-masked (pruned) values table = cube.as_array(include_transforms_for_dims=[0], prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] @@ -559,9 +638,7 @@ def test_cat_x_num_counts_pruned_without_hs(self): def test_mr_x_cat_hs_counts(self): cube = CrunchCube(CR.PETS_X_FRUIT_HS) - expected = np.array([[12, 28, 40], - [12, 22, 34], - [12, 26, 38]]) + expected = np.array([[12, 28, 40], [12, 22, 34], [12, 26, 38]]) actual = cube.as_array(include_transforms_for_dims=[0, 1]) np.testing.assert_array_equal(actual, expected) @@ -569,42 +646,38 @@ def test_mr_x_cat_hs_props_by_cell(self): cube = CrunchCube(CR.PETS_X_FRUIT_HS) # TODO: Change expectation once the MR cell props are fixed. expected = (3, 3) - actual = cube.proportions( - axis=None, include_transforms_for_dims=[0, 1] - ).shape + actual = cube.proportions(axis=None, include_transforms_for_dims=[0, 1]).shape np.testing.assert_array_equal(actual, expected) def test_mr_x_cat_hs_props_by_row(self): cube = CrunchCube(CR.PETS_X_FRUIT_HS) # TODO: Change expectation once the MR cell props are fixed. expected = (3, 3) - actual = cube.proportions( - axis=0, include_transforms_for_dims=[0, 1] - ).shape + actual = cube.proportions(axis=0, include_transforms_for_dims=[0, 1]).shape np.testing.assert_array_equal(actual, expected) def test_mr_x_cat_hs_props_by_col(self): cube = CrunchCube(CR.PETS_X_FRUIT_HS) # TODO: Change expectation once the MR cell props are fixed. expected = (3, 3) - actual = cube.proportions( - axis=1, include_transforms_for_dims=[0, 1] - ).shape + actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1]).shape np.testing.assert_array_equal(actual, expected) def test_missing_cat_hs_labels(self): cube = CrunchCube(CR.MISSING_CAT_HS) # Don't expect the missing category "Non voters" - expected = [[ - 'Whites', - 'White college women voters', - 'White non-college women voters', - 'White college men voters', - 'White non-college men voters', - 'Black voters', - 'Latino and other voters', - ]] + expected = [ + [ + "Whites", + "White college women voters", + "White non-college women voters", + "White college men voters", + "White non-college men voters", + "Black voters", + "Latino and other voters", + ] + ] actual = cube.labels(include_transforms_for_dims=[0]) assert actual == expected @@ -612,40 +685,39 @@ def test_ca_x_cat_counts_with_hs(self): cube = CrunchCube(CR.CA_X_CAT_HS) # Assert counts without H&S - expected = np.array([ - [[1, 1, 0, 0, 0], - [0, 0, 1, 1, 1], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0]], - - [[1, 0, 0, 0, 0], - [0, 1, 0, 1, 0], - [0, 0, 1, 0, 1], - [0, 0, 0, 0, 0]], - - [[0, 0, 0, 0, 0], - [1, 0, 0, 1, 0], - [0, 1, 0, 0, 0], - [0, 0, 1, 0, 1]]]) + expected = np.array( + [ + [[1, 1, 0, 0, 0], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], + [[1, 0, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [0, 0, 0, 0, 0]], + [[0, 0, 0, 0, 0], [1, 0, 0, 1, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 1]], + ] + ) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) # Assert counts with H&S - expected = np.array([ - [[1, 1, 0, 2, 0, 0, 0], - [0, 0, 1, 1, 1, 1, 2], - [0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0]], - - [[1, 0, 0, 1, 0, 0, 0], - [0, 1, 0, 1, 1, 0, 1], - [0, 0, 1, 1, 0, 1, 1], - [0, 0, 0, 0, 0, 0, 0]], - - [[0, 0, 0, 0, 0, 0, 0], - [1, 0, 0, 1, 1, 0, 1], - [0, 1, 0, 1, 0, 0, 0], - [0, 0, 1, 1, 0, 1, 1]]]) + expected = np.array( + [ + [ + [1, 1, 0, 2, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 2], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + ], + [ + [1, 0, 0, 1, 0, 0, 0], + [0, 1, 0, 1, 1, 0, 1], + [0, 0, 1, 1, 0, 1, 1], + [0, 0, 0, 0, 0, 0, 0], + ], + [ + [0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 1, 1, 0, 1], + [0, 1, 0, 1, 0, 0, 0], + [0, 0, 1, 1, 0, 1, 1], + ], + ] + ) # Include transforms for all CA and CAT dims (hence 0, 1 and 2) actual = cube.as_array(include_transforms_for_dims=[0, 1, 2]) @@ -655,11 +727,7 @@ def test_ca_x_cat_margin_with_hs(self): cube = CrunchCube(CR.CA_X_CAT_HS) # Assert counts without H&S - expected = np.array([ - [1, 1, 1, 1, 1], - [1, 1, 1, 1, 1], - [1, 1, 1, 1, 1], - ]) + expected = np.array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]) actual = cube.margin(axis=1, include_transforms_for_dims=[1]) np.testing.assert_array_equal(actual, expected) @@ -667,95 +735,173 @@ def test_cat_x_items_x_cats_margin_with_hs(self): cube = CrunchCube(CR.CAT_X_ITEMS_X_CATS_HS) # Assert counts without H&S - expected = np.array([ - [ - 1287.9364594075469, 2050.0571926339885, 782.9403891997617, - 225.4066607421201, 2622.8036855384603, 974.5889537143403, - 490.5036709315041, 373.8221357520375, - ], - [ - 1147.3697583254452, 2557.8859179678857, 1096.7841912034742, - 374.0411471364339, 1876.3400274431515, 1002.2399030962134, - 457.92228898229905, 419.5110527202654, - ], + expected = np.array( [ - 1053.855075581148, 2699.612841209989, 1427.7399174151794, - 380.8205091587366, 1027.7782011616534, 606.7100283028576, - 218.42735718966821, 265.29362712412535, + [ + 1287.9364594075469, + 2050.0571926339885, + 782.9403891997617, + 225.4066607421201, + 2622.8036855384603, + 974.5889537143403, + 490.5036709315041, + 373.8221357520375, + ], + [ + 1147.3697583254452, + 2557.8859179678857, + 1096.7841912034742, + 374.0411471364339, + 1876.3400274431515, + 1002.2399030962134, + 457.92228898229905, + 419.5110527202654, + ], + [ + 1053.855075581148, + 2699.612841209989, + 1427.7399174151794, + 380.8205091587366, + 1027.7782011616534, + 606.7100283028576, + 218.42735718966821, + 265.29362712412535, + ], ] - ]) + ) actual = cube.margin(axis=2, include_transforms_for_dims=[1, 2]) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_weighted_with_hs(self): cube = CrunchCube(CR.CAT_X_MR_WEIGHTED_HS) - expected = np.array([ - [ - [0.05865163, 0.087823, 0.07486857, 0.0735683, 0., 0.08148267], - [0.20246563, 0.33500382, 0.33176765, 0.27870974, 0.36309359, - 0.33341993], - [0.54592009, 0.45988528, 0.49802406, 0.48137697, 0.51250032, - 0.47855168], - [0.1051054, 0.06727875, 0.0733213, 0.12392602, 0.12440609, - 0.07023618], - [0.05508246, 0.04566041, 0.01379632, 0.02729368, 0., - 0.03006505], - [0.03277479, 0.00434874, 0.0082221, 0.01512529, 0., - 0.00624449], - [0.26111726, 0.42282682, 0.40663622, 0.35227804, 0.36309359, - 0.4149026], - [0.80703735, 0.8827121, 0.90466028, 0.83365501, 0.87559391, - 0.89345428] - ], - [ - [0.00235883, 0.01361576, 0.01328221, 0.01212187, 0., - 0.01345251], - [0.13002321, 0.0591588, 0.09857174, 0.05056353, 0., 0.07844882], - [0.65429951, 0.77915194, 0.74437239, 0.61537442, 1., - 0.76212966], - [0.13730378, 0.11171429, 0.11961331, 0.26739934, 0., - 0.11558033], - [0.04323988, 0.02601641, 0.01593825, 0.02729368, 0., - 0.02108382], - [0.03277479, 0.0103428, 0.0082221, 0.02724716, 0., 0.00930486], - [0.13238204, 0.07277456, 0.11185395, 0.06268541, 0., - 0.09190133], - [0.78668155, 0.85192649, 0.85622634, 0.67805982, 1., 0.85403098] - ], + expected = np.array( [ - [0.003676, 0.00486795, 0.0082221, 0.01212187, 0., 0.00650959], - [0.03884185, 0.00625322, 0.02928964, 0.02729368, 0.12440609, - 0.01752802], - [0.39625335, 0.4717925, 0.44918748, 0.46124151, 0.40543568, - 0.46072884], - [0.4255265, 0.44274565, 0.42191512, 0.43268073, 0.47015822, - 0.43255049], - [0.1054366, 0.07434068, 0.08316356, 0.05153692, 0., 0.07865889], - [0.03026569, 0., 0.0082221, 0.01512529, 0., 0.00402417], - [0.04251785, 0.01112118, 0.03751174, 0.03941555, 0.12440609, - 0.02403761], - [0.4387712, 0.48291368, 0.48669922, 0.50065705, 0.52984178, - 0.48476645] + [ + [0.05865163, 0.087823, 0.07486857, 0.0735683, 0.0, 0.08148267], + [ + 0.20246563, + 0.33500382, + 0.33176765, + 0.27870974, + 0.36309359, + 0.33341993, + ], + [ + 0.54592009, + 0.45988528, + 0.49802406, + 0.48137697, + 0.51250032, + 0.47855168, + ], + [ + 0.1051054, + 0.06727875, + 0.0733213, + 0.12392602, + 0.12440609, + 0.07023618, + ], + [0.05508246, 0.04566041, 0.01379632, 0.02729368, 0.0, 0.03006505], + [0.03277479, 0.00434874, 0.0082221, 0.01512529, 0.0, 0.00624449], + [ + 0.26111726, + 0.42282682, + 0.40663622, + 0.35227804, + 0.36309359, + 0.4149026, + ], + [ + 0.80703735, + 0.8827121, + 0.90466028, + 0.83365501, + 0.87559391, + 0.89345428, + ], + ], + [ + [0.00235883, 0.01361576, 0.01328221, 0.01212187, 0.0, 0.01345251], + [0.13002321, 0.0591588, 0.09857174, 0.05056353, 0.0, 0.07844882], + [0.65429951, 0.77915194, 0.74437239, 0.61537442, 1.0, 0.76212966], + [0.13730378, 0.11171429, 0.11961331, 0.26739934, 0.0, 0.11558033], + [0.04323988, 0.02601641, 0.01593825, 0.02729368, 0.0, 0.02108382], + [0.03277479, 0.0103428, 0.0082221, 0.02724716, 0.0, 0.00930486], + [0.13238204, 0.07277456, 0.11185395, 0.06268541, 0.0, 0.09190133], + [0.78668155, 0.85192649, 0.85622634, 0.67805982, 1.0, 0.85403098], + ], + [ + [0.003676, 0.00486795, 0.0082221, 0.01212187, 0.0, 0.00650959], + [ + 0.03884185, + 0.00625322, + 0.02928964, + 0.02729368, + 0.12440609, + 0.01752802, + ], + [ + 0.39625335, + 0.4717925, + 0.44918748, + 0.46124151, + 0.40543568, + 0.46072884, + ], + [ + 0.4255265, + 0.44274565, + 0.42191512, + 0.43268073, + 0.47015822, + 0.43255049, + ], + [0.1054366, 0.07434068, 0.08316356, 0.05153692, 0.0, 0.07865889], + [0.03026569, 0.0, 0.0082221, 0.01512529, 0.0, 0.00402417], + [ + 0.04251785, + 0.01112118, + 0.03751174, + 0.03941555, + 0.12440609, + 0.02403761, + ], + [ + 0.4387712, + 0.48291368, + 0.48669922, + 0.50065705, + 0.52984178, + 0.48476645, + ], + ], ] - ]) + ) actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1, 2]) np.testing.assert_almost_equal(actual, expected) def test_mr_x_ca_props_by_row_without_hs(self): cube = CrunchCube(CR.MR_X_CA_HS) - expected = np.array([ - [[0.66666667, 0.33333333, 0.00000000, 0.00000000], - [0.33333333, 0.33333333, 0.33333333, 0.00000000], - [0.00000000, 0.33333333, 0.33333333, 0.33333333]], - - [[0.50000000, 0.50000000, 0.00000000, 0.00000000], - [0.25000000, 0.25000000, 0.50000000, 0.00000000], - [0.00000000, 0.25000000, 0.00000000, 0.75000000]], - - [[np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan]], - ]) + expected = np.array( + [ + [ + [0.66666667, 0.33333333, 0.00000000, 0.00000000], + [0.33333333, 0.33333333, 0.33333333, 0.00000000], + [0.00000000, 0.33333333, 0.33333333, 0.33333333], + ], + [ + [0.50000000, 0.50000000, 0.00000000, 0.00000000], + [0.25000000, 0.25000000, 0.50000000, 0.00000000], + [0.00000000, 0.25000000, 0.00000000, 0.75000000], + ], + [ + [np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan], + ], + ] + ) with self.assertRaises(ValueError): # "Table" direction not allowed, because cube's rows are CA dim actual = cube.proportions() @@ -764,25 +910,73 @@ def test_mr_x_ca_props_by_row_without_hs(self): def test_mr_x_ca_props_by_row_with_hs(self): cube = CrunchCube(CR.MR_X_CA_HS) - expected = np.array([ - [[0.66666667, 0.33333333, 1.00000000, 0.00000000, 0.00000000, - 0.00000000, 1.00000000], - [0.33333333, 0.33333333, 0.66666667, 0.33333333, 0.00000000, - 0.33333333, 1.00000000], - [0.00000000, 0.33333333, 0.33333333, 0.33333333, 0.33333333, - 0.66666667, 1.00000000]], - - [[0.50000000, 0.50000000, 1.00000000, 0.00000000, 0.00000000, - 0.00000000, 1.00000000], - [0.25000000, 0.25000000, 0.50000000, 0.50000000, 0.00000000, - 0.50000000, 1.00000000], - [0.00000000, 0.25000000, 0.25000000, 0.00000000, 0.75000000, - 0.75000000, 1.00000000]], - - [[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]], - ]) + expected = np.array( + [ + [ + [ + 0.66666667, + 0.33333333, + 1.00000000, + 0.00000000, + 0.00000000, + 0.00000000, + 1.00000000, + ], + [ + 0.33333333, + 0.33333333, + 0.66666667, + 0.33333333, + 0.00000000, + 0.33333333, + 1.00000000, + ], + [ + 0.00000000, + 0.33333333, + 0.33333333, + 0.33333333, + 0.33333333, + 0.66666667, + 1.00000000, + ], + ], + [ + [ + 0.50000000, + 0.50000000, + 1.00000000, + 0.00000000, + 0.00000000, + 0.00000000, + 1.00000000, + ], + [ + 0.25000000, + 0.25000000, + 0.50000000, + 0.50000000, + 0.00000000, + 0.50000000, + 1.00000000, + ], + [ + 0.00000000, + 0.25000000, + 0.25000000, + 0.00000000, + 0.75000000, + 0.75000000, + 1.00000000, + ], + ], + [ + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + ], + ] + ) with self.assertRaises(ValueError): # "Table" direction not allowed, because cube's rows are CA dim @@ -793,23 +987,27 @@ def test_mr_x_ca_props_by_row_with_hs(self): def test_ca_cat_x_mr_x_ca_subvar_counts_pruning(self): cube = CrunchCube(CR.CA_CAT_X_MR_X_CA_SUBVAR_HS) - expected = np.array([ - [False, False, True], - [False, False, True], - [False, False, True], - [True, True, True], - ]) + expected = np.array( + [ + [False, False, True], + [False, False, True], + [False, False, True], + [True, True, True], + ] + ) actual = cube.as_array(prune=True)[0].mask np.testing.assert_array_equal(actual, expected) def test_ca_cat_x_mr_x_ca_subvar_proportions_pruning(self): cube = CrunchCube(CR.CA_CAT_X_MR_X_CA_SUBVAR_HS) - expected = np.array([ - [False, False, True], - [False, False, True], - [False, False, True], - [True, True, True], - ]) + expected = np.array( + [ + [False, False, True], + [False, False, True], + [False, False, True], + [True, True, True], + ] + ) with self.assertRaises(ValueError): # "Table" direction not allowed cuz CA items @@ -821,23 +1019,27 @@ def test_ca_cat_x_mr_x_ca_subvar_proportions_pruning(self): def test_ca_x_mr_counts_pruning(self): cube = CrunchCube(CR.CA_X_MR_HS) actual = cube.as_array(prune=True)[0].mask - expected = np.array([ - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - [False, False, False, True] - ]) + expected = np.array( + [ + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + ] + ) np.testing.assert_array_equal(actual, expected) def test_ca_x_mr_proportions_pruning(self): cube = CrunchCube(CR.CA_X_MR_HS) - expected = np.array([ - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - [False, False, False, True], - ]) + expected = np.array( + [ + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + [False, False, False, True], + ] + ) actual = cube.proportions(axis=None, prune=True)[0].mask np.testing.assert_array_equal(actual, expected) diff --git a/tests/integration/test_index.py b/tests/integration/test_index.py index 178338909..674b9c3f5 100644 --- a/tests/integration/test_index.py +++ b/tests/integration/test_index.py @@ -11,36 +11,38 @@ class TestIndex(TestCase): - def test_mr_x_cat_index(self): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [0.95865152585539, 1.0385904443566], - [1.02305106635277, 0.9784320457270], - [0.97603114632311, 1.0224274029149], - [0.98102944430498, 1.0182906820384], - [1.14466510106092, 0.8606566846476], - [0.99292572005336, 1.0068293374540] - ]) + expected = np.array( + [ + [0.95865152585539, 1.0385904443566], + [1.02305106635277, 0.9784320457270], + [0.97603114632311, 1.0224274029149], + [0.98102944430498, 1.0182906820384], + [1.14466510106092, 0.8606566846476], + [0.99292572005336, 1.0068293374540], + ] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_index(self): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [0.8571429, 1.1152941, 0.9610984], - [1.0769231, 0.9466231, 1.019037], - ]) + expected = np.array( + [[0.8571429, 1.1152941, 0.9610984], [1.0769231, 0.9466231, 1.019037]] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_mr_x_mr_index(self): cube = CrunchCube(CR.PETS_X_PETS) - expected = np.array([ - [1.0000000000000000, 1.1724137931034484, 0.894736842105263], - [0.8529411764705883, 1.0000000000000000, 0.763157894736842], - [1.1176470588235294, 1.310344827586207, 1.0000000000000000] - ]) + expected = np.array( + [ + [1.0000000000000000, 1.1724137931034484, 0.894736842105263], + [0.8529411764705883, 1.0000000000000000, 0.763157894736842], + [1.1176470588235294, 1.310344827586207, 1.0000000000000000], + ] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) @@ -48,41 +50,53 @@ def test_ca_items_x_ca_cat_x_cat_index(self): cube = CrunchCube(CR.CA_ITEMS_X_CA_CAT_X_CAT) # Test index values - expected = np.array([ - [[1., 1., np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan]], - - [[2., 0., np.nan, np.nan, np.nan], - [0., 2., np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan]], - - [[np.nan, np.nan, np.nan, np.nan, np.nan], - [2., 0., np.nan, np.nan, np.nan], - [0., 2., np.nan, np.nan, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan]], - ]) + expected = np.array( + [ + [ + [1.0, 1.0, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + [ + [2.0, 0.0, np.nan, np.nan, np.nan], + [0.0, 2.0, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + [ + [np.nan, np.nan, np.nan, np.nan, np.nan], + [2.0, 0.0, np.nan, np.nan, np.nan], + [0.0, 2.0, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + ] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) # Test pruning mask - expected = np.array([ - [[False, False, True, True, True], - [True, True, True, True, True], - [True, True, True, True, True], - [True, True, True, True, True]], - - [[False, False, True, True, True], - [False, False, True, True, True], - [True, True, True, True, True], - [True, True, True, True, True]], - - [[True, True, True, True, True], - [False, False, True, True, True], - [False, False, True, True, True], - [True, True, True, True, True]], - ]) + expected = np.array( + [ + [ + [False, False, True, True, True], + [True, True, True, True, True], + [True, True, True, True, True], + [True, True, True, True, True], + ], + [ + [False, False, True, True, True], + [False, False, True, True, True], + [True, True, True, True, True], + [True, True, True, True, True], + ], + [ + [True, True, True, True, True], + [False, False, True, True, True], + [False, False, True, True, True], + [True, True, True, True, True], + ], + ] + ) actual = Index.data(cube, weighted=True, prune=True).mask np.testing.assert_array_equal(actual, expected) diff --git a/tests/integration/test_index_table.py b/tests/integration/test_index_table.py index d7f978717..af74cc8ae 100644 --- a/tests/integration/test_index_table.py +++ b/tests/integration/test_index_table.py @@ -1,4 +1,4 @@ -'''This module contains tests for the correct index functionality.''' +"""This module contains tests for the correct index functionality.""" # pylint: disable=missing-docstring, invalid-name @@ -11,68 +11,62 @@ def test_cat_x_cat_slice_column_index(): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [100, 80], - [100, 120], - ]) + expected = np.array([[100, 80], [100, 120]]) actual = cube.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) def test_cat_x_cat_slice_row_index(): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [107.142857142857, 85.7142857142857], - [93.75, 112.5], - ]) + expected = np.array([[107.142857142857, 85.7142857142857], [93.75, 112.5]]) actual = cube.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) def test_cat_x_cat_slice_row_index_with_baseline(): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [119.047619047619, 71.4285714285714], - [104.16666666666667, 93.75], - ]) + expected = np.array( + [[119.047619047619, 71.4285714285714], [104.16666666666667, 93.75]] + ) actual = cube.slices[0].index_table(axis=1, baseline=np.array([0.6, 0.4])) np.testing.assert_almost_equal(actual, expected) def test_cat_x_cat_slice_column_index_with_baseline(): cube = CrunchCube(CR.CAT_X_CAT) - expected = np.array([ - [83.3333333333333, 66.6666666666667], - [125, 150], - ]) + expected = np.array([[83.3333333333333, 66.6666666666667], [125, 150]]) actual = cube.slices[0].index_table(axis=0, baseline=np.array([0.6, 0.4])) np.testing.assert_almost_equal(actual, expected) def test_mr_x_cat_slice_column_index(): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [95.8651525855387, 103.859044435659], - [102.305106635277, 97.8432045727022], - [97.6031146323114, 102.24274029149], - [98.1029444304978, 101.829068203842], - [114.466510106092, 86.0656684647625], - [99.2925720053358, 100.682933745397], - ]) + expected = np.array( + [ + [95.8651525855387, 103.859044435659], + [102.305106635277, 97.8432045727022], + [97.6031146323114, 102.24274029149], + [98.1029444304978, 101.829068203842], + [114.466510106092, 86.0656684647625], + [99.2925720053358, 100.682933745397], + ] + ) actual = cube.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) def test_mr_x_cat_slice_row_index(): cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [95.3416155822363, 104.394053238208], - [101.879419344372, 98.2272247381305], - [97.1985863211465, 102.642452778304], - [99.2098729346168, 100.745292805163], - [115.700063998356, 85.1908063256891], - [100.477252947149, 99.5498278652431], - ]) + expected = np.array( + [ + [95.3416155822363, 104.394053238208], + [101.879419344372, 98.2272247381305], + [97.1985863211465, 102.642452778304], + [99.2098729346168, 100.745292805163], + [115.700063998356, 85.1908063256891], + [100.477252947149, 99.5498278652431], + ] + ) actual = cube.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -80,45 +74,62 @@ def test_mr_x_cat_slice_row_index(): def test_mr_x_mr_slice_column_index(): mr_x_mr = CrunchCube(CR.FULL_CUBE) mr_alone = CrunchCube(CR.MR_WGTD) - expected = ( - mr_x_mr.proportions(axis=0) / - mr_alone.proportions()[:, None] * 100 - ) + expected = mr_x_mr.proportions(axis=0) / mr_alone.proportions()[:, None] * 100 actual = mr_x_mr.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) def test_mr_x_mr_slice_row_index(): mr_x_mr = CrunchCube(CR.FULL_CUBE) - expected = np.array([ - 96.5399786, 101.08725891, 89.22034634, 89.31908705, - 97.03625304, 99.96205366, 79.74421663, 94.32481007, - 98.95581177, 101.14422043, 95.50739913, 91.82091585, - 92.66856944, 102.10571127, 94.88279498, 84.22596655, - 92.62629722, 86.77934972, 99.31115914, 98.72846269, - 99.54678433, 94.13302782, 101.99733805, 102.24392708, - 97.87112979, 95.08750269, 100.61288629, - ]) + expected = np.array( + [ + 96.5399786, + 101.08725891, + 89.22034634, + 89.31908705, + 97.03625304, + 99.96205366, + 79.74421663, + 94.32481007, + 98.95581177, + 101.14422043, + 95.50739913, + 91.82091585, + 92.66856944, + 102.10571127, + 94.88279498, + 84.22596655, + 92.62629722, + 86.77934972, + 99.31115914, + 98.72846269, + 99.54678433, + 94.13302782, + 101.99733805, + 102.24392708, + 97.87112979, + 95.08750269, + 100.61288629, + ] + ) actual = mr_x_mr.slices[0].index_table(axis=1)[0] np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_slice_column_index(): cat_x_mr = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [90.9090909, 106.9518717, 95.6937799], - [104.4776119, 96.5759438, 102.1209741], - ]) + expected = np.array( + [[90.9090909, 106.9518717, 95.6937799], [104.4776119, 96.5759438, 102.1209741]] + ) actual = cat_x_mr.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_slice_row_index(): cat_x_mr = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [85.7142857, 111.5294118, 96.1098398], - [107.6923077, 94.6623094, 101.9036954], - ]) + expected = np.array( + [[85.7142857, 111.5294118, 96.1098398], [107.6923077, 94.6623094, 101.9036954]] + ) actual = cat_x_mr.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -126,19 +137,23 @@ def test_cat_x_mr_slice_row_index(): def test_mr_x_mr_index_tables_parity_with_whaam_and_r(): cat_x_mr = CrunchCube(CR.MR_X_MR_INDEX_TABLE) # Test column direction - expected = np.array([ - [192.05298013, 97.23165321, 89.68799602], - [99.22588537, 239.38592924, 95.99096915], - [93.52597694, 98.08689727, 182.31556654], - ]) + expected = np.array( + [ + [192.05298013, 97.23165321, 89.68799602], + [99.22588537, 239.38592924, 95.99096915], + [93.52597694, 98.08689727, 182.31556654], + ] + ) actual = cat_x_mr.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) # Test row direction - expected = np.array([ - [192.0529801, 99.2258854, 93.5259769], - [97.2316532, 239.3859292, 98.0868973], - [89.687996, 95.9909692, 182.3155665], - ]) + expected = np.array( + [ + [192.0529801, 99.2258854, 93.5259769], + [97.2316532, 239.3859292, 98.0868973], + [89.687996, 95.9909692, 182.3155665], + ] + ) actual = cat_x_mr.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -146,21 +161,25 @@ def test_mr_x_mr_index_tables_parity_with_whaam_and_r(): def test_mr_x_3vl_index_tables_parity_with_nssat(): mr_x_3vl = CrunchCube(CR.NSSAT_MR_X_3vl) # Test column direction - expected = np.array([ - [179.793686976007, 90.4924459426829], - [182.343952039497, 88.5838171105893], - [84.6174957937067, 101.993855386627], - [np.nan, np.nan] - ]) + expected = np.array( + [ + [179.793686976007, 90.4924459426829], + [182.343952039497, 88.5838171105893], + [84.6174957937067, 101.993855386627], + [np.nan, np.nan], + ] + ) actual = mr_x_3vl.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) # Test row direction - expected = np.array([ - [179.360970521192, 90.2746542556969], - [184.52243729878, 89.6421386925666], - [84.5355650535557, 101.895100017134], - [np.nan, np.nan] - ]) + expected = np.array( + [ + [179.360970521192, 90.2746542556969], + [184.52243729878, 89.6421386925666], + [84.5355650535557, 101.895100017134], + [np.nan, np.nan], + ] + ) actual = mr_x_3vl.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -168,29 +187,85 @@ def test_mr_x_3vl_index_tables_parity_with_nssat(): def test_mr_x_mr_index_tables_parity_with_nssat(): mr_x_mr = CrunchCube(CR.NSSAT_MR_X_MR) # Test column direction - expected = np.array([ - [114.917891097666, 94.6007480891202, 75.7981149285497, - 41.5084915084915, 64.5687645687646, 581.118881118881, np.nan, 0, - np.nan], - [90.0597657183839, 95.9426026719446, 102.497687326549, - 84.1945288753799, 261.93853427896, 0, np.nan, 0, np.nan], - [99.4879510762734, 101.567130443518, 101.446145177951, - 106.834310398025, 86.4170866330693, 59.8272138228942, np.nan, - 119.654427645788, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan] - ]) + expected = np.array( + [ + [ + 114.917891097666, + 94.6007480891202, + 75.7981149285497, + 41.5084915084915, + 64.5687645687646, + 581.118881118881, + np.nan, + 0, + np.nan, + ], + [ + 90.0597657183839, + 95.9426026719446, + 102.497687326549, + 84.1945288753799, + 261.93853427896, + 0, + np.nan, + 0, + np.nan, + ], + [ + 99.4879510762734, + 101.567130443518, + 101.446145177951, + 106.834310398025, + 86.4170866330693, + 59.8272138228942, + np.nan, + 119.654427645788, + np.nan, + ], + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + ] + ) actual = mr_x_mr.slices[0].index_table(axis=0) np.testing.assert_almost_equal(actual, expected) # Test row direction - expected = np.array([ - [104.349919743178, 85.9011627906977, 68.8276397515528, 37.6913265306122, - 58.6309523809524, 527.678571428571, np.nan, 0, np.nan], - [98.1631656082071, 104.575328614762, 111.7202268431, 91.7701863354037, - 285.507246376812, 0, np.nan, 0, np.nan], - [99.6740889304191, 101.757158356526, 101.635946732516, 107.03419298754, - 86.57876943881, 59.9391480730223, np.nan, 119.878296146045, np.nan], - [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan] - ]) + expected = np.array( + [ + [ + 104.349919743178, + 85.9011627906977, + 68.8276397515528, + 37.6913265306122, + 58.6309523809524, + 527.678571428571, + np.nan, + 0, + np.nan, + ], + [ + 98.1631656082071, + 104.575328614762, + 111.7202268431, + 91.7701863354037, + 285.507246376812, + 0, + np.nan, + 0, + np.nan, + ], + [ + 99.6740889304191, + 101.757158356526, + 101.635946732516, + 107.03419298754, + 86.57876943881, + 59.9391480730223, + np.nan, + 119.878296146045, + np.nan, + ], + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + ] + ) actual = mr_x_mr.slices[0].index_table(axis=1) np.testing.assert_almost_equal(actual, expected) @@ -202,12 +277,8 @@ def test_mr_single_cat_x_mr(): np.testing.assert_array_equal(cube_slice.index_table(axis=1), expected) # With pruning - expected = np.ma.masked_array( - [[100, 100, np.nan]], mask=[[False, False, True]] - ) - np.testing.assert_array_equal( - cube_slice.index_table(axis=0, prune=True), expected - ) + expected = np.ma.masked_array([[100, 100, np.nan]], mask=[[False, False, True]]) + np.testing.assert_array_equal(cube_slice.index_table(axis=0, prune=True), expected) def test_mr_x_mr_single_cat(): @@ -217,6 +288,4 @@ def test_mr_x_mr_single_cat(): # With pruning expected = np.ma.masked_array([100, 100, np.nan], mask=[False, False, True]) - np.testing.assert_array_equal( - cube_slice.index_table(axis=0, prune=True), expected - ) + np.testing.assert_array_equal(cube_slice.index_table(axis=0, prune=True), expected) diff --git a/tests/integration/test_multiple_response.py b/tests/integration/test_multiple_response.py index f22e7fe88..bd358acec 100644 --- a/tests/integration/test_multiple_response.py +++ b/tests/integration/test_multiple_response.py @@ -13,14 +13,14 @@ def test_labels_simple_mr_exclude_missing(): cube = CrunchCube(CR.SIMPLE_MR) - expected = [['Response #1', 'Response #2', 'Response #3']] + expected = [["Response #1", "Response #2", "Response #3"]] actual = cube.labels() assert actual == expected def test_labels_simple_mr_include_missing_does_not_break(): cube = CrunchCube(CR.SIMPLE_MR) - expected = [['Response #1', 'Response #2', 'Response #3']] + expected = [["Response #1", "Response #2", "Response #3"]] actual = cube.labels(include_missing=True) assert actual == expected @@ -41,7 +41,7 @@ def test_margin_simple_mr_axis_none(): def test_proportions_simple_mr(): cube = CrunchCube(CR.SIMPLE_MR) - expected = np.array([0.6, 0.6666667, 0.]) + expected = np.array([0.6, 0.6666667, 0.0]) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) @@ -55,30 +55,21 @@ def test_proportions_simple_mr_prune(): def test_labels_cat_x_mr_exclude_missing(): cube = CrunchCube(CR.CAT_X_MR) - expected = [ - ['rambutan', 'satsuma'], - ['dog', 'cat', 'wombat'], - ] + expected = [["rambutan", "satsuma"], ["dog", "cat", "wombat"]] actual = cube.labels() assert actual == expected def test_labels_cat_x_mr_include_missing(): cube = CrunchCube(CR.CAT_X_MR) - expected = [ - ['rambutan', 'satsuma', 'No Data'], - ['dog', 'cat', 'wombat'], - ] + expected = [["rambutan", "satsuma", "No Data"], ["dog", "cat", "wombat"]] actual = cube.labels(include_missing=True) assert actual == expected def test_as_array_cat_x_mr(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [12, 12, 12], - [28, 22, 26], - ]) + expected = np.array([[12, 12, 12], [28, 22, 26]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) @@ -87,10 +78,7 @@ def test_as_array_cat_x_mr_pruned_row(): cube = CrunchCube(CR.CAT_X_MR_PRUNED_ROW) # Not pruned - expected = np.array([ - [12, 12, 12], - [0, 0, 0], - ]) + expected = np.array([[12, 12, 12], [0, 0, 0]]) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) @@ -105,17 +93,11 @@ def test_as_array_cat_x_mr_pruned_col(): # Not pruned actual = cube.as_array() - expected = np.array([ - [6, 6, 0], - [16, 12, 0], - ]) + expected = np.array([[6, 6, 0], [16, 12, 0]]) np.testing.assert_array_equal(actual, expected) # Pruned - expected = np.array([ - [6, 6], - [16, 12], - ]) + expected = np.array([[6, 6], [16, 12]]) actual = np.ma.compress_cols(cube.as_array(prune=True)) np.testing.assert_array_equal(actual, expected) @@ -125,10 +107,7 @@ def test_as_array_cat_x_mr_pruned_row_col(): # Not pruned actual = cube.as_array() - expected = np.array([ - [6, 6, 0], - [0, 0, 0], - ]) + expected = np.array([[6, 6, 0], [0, 0, 0]]) np.testing.assert_array_equal(actual, expected) # Pruned @@ -143,19 +122,11 @@ def test_as_array_mr_x_cat_pruned_col(): # Not pruned actual = cube.as_array() - expected = np.array([ - [12, 0], - [12, 0], - [12, 0], - ]) + expected = np.array([[12, 0], [12, 0], [12, 0]]) np.testing.assert_array_equal(actual, expected) # Pruned - expected = np.array([ - [12], - [12], - [12], - ]) + expected = np.array([[12], [12], [12]]) actual = np.ma.compress_cols(cube.as_array(prune=True)) np.testing.assert_array_equal(actual, expected) @@ -165,18 +136,11 @@ def test_as_array_mr_x_cat_pruned_row(): # Not pruned actual = cube.as_array() - expected = np.array([ - [6, 16], - [6, 12], - [0, 0], - ]) + expected = np.array([[6, 16], [6, 12], [0, 0]]) np.testing.assert_array_equal(actual, expected) # Pruned - expected = np.array([ - [6, 16], - [6, 12], - ]) + expected = np.array([[6, 16], [6, 12]]) actual = np.ma.compress_rows(cube.as_array(prune=True)) np.testing.assert_array_equal(actual, expected) @@ -186,18 +150,11 @@ def test_as_array_mr_x_cat_pruned_row_col(): # Not pruned actual = cube.as_array() - expected = np.array([ - [6, 0], - [6, 0], - [0, 0], - ]) + expected = np.array([[6, 0], [6, 0], [0, 0]]) np.testing.assert_array_equal(actual, expected) # Pruned - expected = np.array([ - [6], - [6], - ]) + expected = np.array([[6], [6]]) table = cube.as_array(prune=True) actual = table[:, ~table.mask.all(axis=0)][~table.mask.all(axis=1), :] np.testing.assert_array_equal(actual, expected) @@ -219,93 +176,87 @@ def test_margin_cat_x_mr_by_col(): def test_proportions_cat_x_mr_by_cell(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [0.15, 0.15189873, 0.17142857], - [0.35, 0.27848101, 0.37142857], - ]) + expected = np.array( + [[0.15, 0.15189873, 0.17142857], [0.35, 0.27848101, 0.37142857]] + ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_mr_by_col(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [.3, .3529412, .3157895], - [.7, .6470588, .6842105], - ]) + expected = np.array([[0.3, 0.3529412, 0.3157895], [0.7, 0.6470588, 0.6842105]]) actual = cube.proportions(axis=0) np.testing.assert_almost_equal(actual, expected) def test_proportions_cat_x_mr_by_row(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [0.42857143, 0.48, 0.52173913], - [0.53846154, 0.40740741, 0.55319149], - ]) + expected = np.array( + [[0.42857143, 0.48, 0.52173913], [0.53846154, 0.40740741, 0.55319149]] + ) actual = cube.proportions(axis=1) np.testing.assert_almost_equal(actual, expected) def test_z_scores_from_r_row_margin(): cube = CrunchCube(CR.MR_X_CAT_PROFILES_STATS_WEIGHTED) - expected = np.array([ - [ - -1.465585354569577, - 3.704125875262655, - 3.823689449491973, - 1.53747452587281, - 2.584734165643072, - -7.488143461076757, - -0.248968750486873, - 0.794143540856786 - ], + expected = np.array( [ - 1.465585354569564, - -3.704125875262655, - -3.823689449491981, - -1.537474525872799, - -2.584734165643066, - 7.488143461076757, - 0.248968750486873, - -0.794143540856781 + [ + -1.465585354569577, + 3.704125875262655, + 3.823689449491973, + 1.53747452587281, + 2.584734165643072, + -7.488143461076757, + -0.248968750486873, + 0.794143540856786, + ], + [ + 1.465585354569564, + -3.704125875262655, + -3.823689449491981, + -1.537474525872799, + -2.584734165643066, + 7.488143461076757, + 0.248968750486873, + -0.794143540856781, + ], ] - ]) + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_index_by_row(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [.8571429, 1.1152941, .9610984], - [1.0769231, .9466231, 1.019037], - ]) + expected = np.array( + [[0.8571429, 1.1152941, 0.9610984], [1.0769231, 0.9466231, 1.019037]] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_index_by_cell(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [.8571429, 1.1152941, .9610984], - [1.0769231, .9466231, 1.019037], - ]) + expected = np.array( + [[0.8571429, 1.1152941, 0.9610984], [1.0769231, 0.9466231, 1.019037]] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_index_by_col(): cube = CrunchCube(CR.CAT_X_MR) - expected = np.array([ - [.8571429, 1.1152941, .9610984], - [1.0769231, .9466231, 1.019037], - ]) + expected = np.array( + [[0.8571429, 1.1152941, 0.9610984], [1.0769231, 0.9466231, 1.019037]] + ) actual = Index.data(cube, weighted=True, prune=False) np.testing.assert_almost_equal(actual, expected) -@patch('cr.cube.crunch_cube.CrunchCube.mr_dim_ind', 2) +@patch("cr.cube.crunch_cube.CrunchCube.mr_dim_ind", 2) def test_cat_x_mr_index_bad_direction(): cube = CrunchCube(CR.CAT_X_MR) with pytest.raises(ValueError): @@ -314,22 +265,45 @@ def test_cat_x_mr_index_bad_direction(): def test_mr_x_single_wave(): cube = CrunchCube(CR.MR_X_SINGLE_WAVE) - expected = np.array([ - 308.32755712, 187.06825269, 424.82328071, 72.68885079, - 273.15993803, 467.62527785, 62.183386, 442.80441811, - 281.57825919, 0., 237.35065847, 233.19692455, 0., 0., 0., 0., - 0., 0., 0., 38.05075633, 90.93234493, 123.22747266, 142.42909713, - ]) + expected = np.array( + [ + 308.32755712, + 187.06825269, + 424.82328071, + 72.68885079, + 273.15993803, + 467.62527785, + 62.183386, + 442.80441811, + 281.57825919, + 0.0, + 237.35065847, + 233.19692455, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 38.05075633, + 90.93234493, + 123.22747266, + 142.42909713, + ] + ) actual = cube.margin(axis=1) np.testing.assert_almost_equal(actual, expected) def test_array_x_mr_by_col(): cube = CrunchCube(CR.CA_SUBVAR_X_CA_CAT_X_MR) - expected = np.array([ - [0.5146153267487166, 0.04320534228100489, 0.5933354514113938], - [0.4853846732512835, 0.9567946577189951, 0.4066645485886063], - ]) + expected = np.array( + [ + [0.5146153267487166, 0.04320534228100489, 0.5933354514113938], + [0.4853846732512835, 0.9567946577189951, 0.4066645485886063], + ] + ) # Only compare the first slice (parity with whaam tests) actual = cube.proportions(axis=1)[0] np.testing.assert_almost_equal(actual, expected) @@ -337,10 +311,12 @@ def test_array_x_mr_by_col(): def test_array_x_mr_by_row(): cube = CrunchCube(CR.CA_SUBVAR_X_CA_CAT_X_MR) - expected = np.array([ - [0.41922353375674093, 0.03471395310157275, 0.5832027484767315], - [0.5143557893611596, 1, 0.5199603338915276], - ]) + expected = np.array( + [ + [0.41922353375674093, 0.03471395310157275, 0.5832027484767315], + [0.5143557893611596, 1, 0.5199603338915276], + ] + ) # Only compare the first slice (parity with whaam tests) actual = cube.proportions(axis=2)[0] np.testing.assert_almost_equal(actual, expected) @@ -348,10 +324,9 @@ def test_array_x_mr_by_row(): def test_array_x_mr_by_cell(): cube = CrunchCube(CR.CA_SUBVAR_X_CA_CAT_X_MR) - expected = np.array([ - [0.23701678, 0.01962626, 0.32972586], - [0.223554, 0.43462911, 0.2259899], - ]) + expected = np.array( + [[0.23701678, 0.01962626, 0.32972586], [0.223554, 0.43462911, 0.2259899]] + ) # Only compare the first slice (parity with whaam tests) actual = cube.proportions(axis=None)[0] np.testing.assert_almost_equal(actual, expected) @@ -384,15 +359,20 @@ def test_cat_x_mr_x_mr_proportions_by_row(): # TODO: Check with Jon and Mike. This expectation is the same as doing # prop.table(cube, c(1, 2)) in R (same numbers, different slicing). - expected = np.array([ - [[0.19169699, 0.5949388], - [0.19543651, 0.59920635], - [0.19712526, 0.59753593]], - - [[0.17207792, 0.1017316], - [0.1963129, 0.10380335], - [0.19141804, 0.10442508]], - ]) + expected = np.array( + [ + [ + [0.19169699, 0.5949388], + [0.19543651, 0.59920635], + [0.19712526, 0.59753593], + ], + [ + [0.17207792, 0.1017316], + [0.1963129, 0.10380335], + [0.19141804, 0.10442508], + ], + ] + ) np.testing.assert_almost_equal(actual, expected) @@ -400,27 +380,15 @@ def test_cat_x_mr_x_mr_pruned_rows(): cube = CrunchCube(CR.CAT_X_MR_X_MR_PRUNED_ROWS) # Not pruned - expected = np.array([ - [[0, 2, 2], - [1, 3, 2], - [0, 0, 0]], - - [[3, 3, 6], - [0, 3, 4], - [0, 0, 0]], - ]) + expected = np.array( + [[[0, 2, 2], [1, 3, 2], [0, 0, 0]], [[3, 3, 6], [0, 3, 4], [0, 0, 0]]] + ) actual = cube.as_array() np.testing.assert_array_equal(actual, expected) # Pruned - expected_0th_tab = np.array([ - [0, 2, 2], - [1, 3, 2], - ]) - expected_1st_tab = np.array([ - [3, 3, 6], - [0, 3, 4], - ]) + expected_0th_tab = np.array([[0, 2, 2], [1, 3, 2]]) + expected_1st_tab = np.array([[3, 3, 6], [0, 3, 4]]) actual_0th_tab = np.ma.compress_rows(cube.as_array(prune=True)[0]) np.testing.assert_array_equal(actual_0th_tab, expected_0th_tab) @@ -432,24 +400,28 @@ def test_cat_x_mr_x_mr_pruned_cols(): cube = CrunchCube(CR.CAT_X_MR_X_MR_EMPTY_COLS) # Not pruned - expected = np.array([ - [1.42180119, 5.67259693, 0.00000000, 0.], - [5.96105631, 1.46479350, 22.51724162, 0.], - [1.79182255, 1.19879791, 23.60391651, 0.], - [4.67364825, 8.02124010, 93.65643860, 0.], - [16.0107376, 13.06260544, 206.93592858, 0.], - ]) + expected = np.array( + [ + [1.42180119, 5.67259693, 0.00000000, 0.0], + [5.96105631, 1.46479350, 22.51724162, 0.0], + [1.79182255, 1.19879791, 23.60391651, 0.0], + [4.67364825, 8.02124010, 93.65643860, 0.0], + [16.0107376, 13.06260544, 206.93592858, 0.0], + ] + ) actual = cube.as_array()[0] np.testing.assert_almost_equal(actual, expected) # Pruned - expected = np.array([ - [1.42180119, 5.67259693, 0.], - [5.96105631, 1.46479350, 22.51724162], - [1.79182255, 1.19879791, 23.60391651], - [4.67364825, 8.02124010, 93.65643860], - [16.0107376, 13.06260544, 206.93592858], - ]) + expected = np.array( + [ + [1.42180119, 5.67259693, 0.0], + [5.96105631, 1.46479350, 22.51724162], + [1.79182255, 1.19879791, 23.60391651], + [4.67364825, 8.02124010, 93.65643860], + [16.0107376, 13.06260544, 206.93592858], + ] + ) actual = np.ma.compress_cols(cube.as_array(prune=True)[0]) np.testing.assert_almost_equal(actual, expected) @@ -470,15 +442,16 @@ def test_cat_x_mr_x_mr_proportions_by_col(): # TODO: Check with Jon and Mike. Corresponds to # R's prop.table(cube, c(1, 3)) - expected = np.array([ - [[0.60553814, 0.60372608], - [0.10292581, 0.1013763], - [0.10031348, 0.09768379]], - - [[0.08141321, 0.09003831], - [0.60522273, 0.598659], - [0.58474142, 0.5967433]], - ]) + expected = np.array( + [ + [ + [0.60553814, 0.60372608], + [0.10292581, 0.1013763], + [0.10031348, 0.09768379], + ], + [[0.08141321, 0.09003831], [0.60522273, 0.598659], [0.58474142, 0.5967433]], + ] + ) np.testing.assert_almost_equal(actual, expected) @@ -497,15 +470,12 @@ def test_cat_x_mr_x_mr_proportions_by_cell(): # TODO: Check w Jon/Mike # Same as prop.table(cube, 1) in R - expected = np.array([ - [[0.1159, 0.3597], - [0.0197, 0.0604], - [0.0192, 0.0582]], - - [[0.0159, 0.0094], - [0.1182, 0.0625], - [0.1142, 0.0623]], - ]) + expected = np.array( + [ + [[0.1159, 0.3597], [0.0197, 0.0604], [0.0192, 0.0582]], + [[0.0159, 0.0094], [0.1182, 0.0625], [0.1142, 0.0623]], + ] + ) np.testing.assert_almost_equal(actual, expected) @@ -513,11 +483,13 @@ def test_mr_x_cat_x_cat_by_col(): # TODO: Check expectations with Mike and Jon cube = CrunchCube(CR.SELECTED_3WAY_2_FILLEDMISSING) # Only compare 0 slice (parity with whaam tests) - expected = np.array([ - [0.5923110874002918, 0.3758961399306439], - [0, 0], - [0.49431928922535223, 0.6091963925363675] - ]) + expected = np.array( + [ + [0.5923110874002918, 0.3758961399306439], + [0, 0], + [0.49431928922535223, 0.6091963925363675], + ] + ) # 3D cube => col == 1 actual = cube.proportions(axis=1)[0] np.testing.assert_almost_equal(actual, expected) @@ -527,11 +499,13 @@ def test_cat_x_mr_x_cat_by_col(): # TODO: Check expectations with Mike and Jon cube = CrunchCube(CR.SELECTED_3WAY_FILLEDMISSING) # Only take first slice (parity with whaam tests). - expected = np.array([ - [0.0997975162008577, np.nan], - [0.20327963774693497, np.nan], - [0.3113417143573762, np.nan], - ]) + expected = np.array( + [ + [0.0997975162008577, np.nan], + [0.20327963774693497, np.nan], + [0.3113417143573762, np.nan], + ] + ) # 3D cube => col == 1 actual = cube.proportions(axis=1)[0] np.testing.assert_almost_equal(actual, expected) @@ -553,11 +527,9 @@ def test_cat_x_mr_x_cat_by_cell(): # Only take first slice (parity with whaam tests). # TODO: Check with @jonkeane, since R results are slightly # different. (It's using (0, 2) rather than (1, 2) axis). - expected = np.array([ - [0.0997975162008577, 0], - [0.20327963774693497, 0], - [0.3113417143573762, 0], - ]) + expected = np.array( + [[0.0997975162008577, 0], [0.20327963774693497, 0], [0.3113417143573762, 0]] + ) # Old expectation: # expected = np.array([ # [0.03326584, 0], @@ -570,38 +542,114 @@ def test_cat_x_mr_x_cat_by_cell(): def test_mr_props_pruned(): cube = CrunchCube(CR.PROMPTED_AWARENESS) - expected = np.array([ - 9.70083312e-01, 9.53131845e-01, 9.64703914e-01, - 9.59703205e-01, 9.37891446e-01, 8.84137923e-01, - 7.77056917e-01, 7.15135296e-01, 9.03057657e-01, - 8.67103783e-01, 8.38011719e-01, 8.60897234e-01, - 7.68101070e-01, 7.59030477e-01, 8.66127931e-01, - 6.89111039e-01, 7.39338305e-01, 1.89895586e-01, - 1.95866187e-01, 8.90452848e-01, 6.10278144e-01, - 6.35237428e-01, 6.54874171e-01, 6.89736947e-01, - 2.31607423e-01, 4.44608376e-01, 6.06987388e-01, - 4.16165746e-01, 2.06262071e-01, 2.08512519e-01, - 1.59533129e-01, 1.86245154e-01, 1.01661334e-01, - 1.82235674e-01, 7.30060936e-01, 4.45912391e-01, - 4.87037442e-01, 1.29527814e-01, 4.95486986e-01, - 2.84392427e-01, 3.93962082e-01, 3.91279968e-01, - 8.96639874e-02, 9.50985735e-04, 1.35477929e-01, - 1.86531215e-01, - ]) + expected = np.array( + [ + 9.70083312e-01, + 9.53131845e-01, + 9.64703914e-01, + 9.59703205e-01, + 9.37891446e-01, + 8.84137923e-01, + 7.77056917e-01, + 7.15135296e-01, + 9.03057657e-01, + 8.67103783e-01, + 8.38011719e-01, + 8.60897234e-01, + 7.68101070e-01, + 7.59030477e-01, + 8.66127931e-01, + 6.89111039e-01, + 7.39338305e-01, + 1.89895586e-01, + 1.95866187e-01, + 8.90452848e-01, + 6.10278144e-01, + 6.35237428e-01, + 6.54874171e-01, + 6.89736947e-01, + 2.31607423e-01, + 4.44608376e-01, + 6.06987388e-01, + 4.16165746e-01, + 2.06262071e-01, + 2.08512519e-01, + 1.59533129e-01, + 1.86245154e-01, + 1.01661334e-01, + 1.82235674e-01, + 7.30060936e-01, + 4.45912391e-01, + 4.87037442e-01, + 1.29527814e-01, + 4.95486986e-01, + 2.84392427e-01, + 3.93962082e-01, + 3.91279968e-01, + 8.96639874e-02, + 9.50985735e-04, + 1.35477929e-01, + 1.86531215e-01, + ] + ) actual = np.ma.compressed(cube.proportions(prune=True)) np.testing.assert_almost_equal(actual, expected) def test_mr_counts_not_pruned(): cube = CrunchCube(CR.PROMPTED_AWARENESS) - expected = np.array([ - 224833, 221990, 223560, 222923, 217586, 206164, 183147, 167720, - 209355, 201847, 193826, 198744, 180015, 174349, 200050, 160769, - 167969, 43193, 44339, 207539, 135973, 146002, 146789, 160692, - 53995, 95741, 135700, 91878, 48465, 48929, 35189, 42764, - 21194, 41422, 167652, 95676, 111961, 26137, 0, 0, 111760, 60761, - 87645, 85306, 18873, 178, 30461, 42843, - ]) + expected = np.array( + [ + 224833, + 221990, + 223560, + 222923, + 217586, + 206164, + 183147, + 167720, + 209355, + 201847, + 193826, + 198744, + 180015, + 174349, + 200050, + 160769, + 167969, + 43193, + 44339, + 207539, + 135973, + 146002, + 146789, + 160692, + 53995, + 95741, + 135700, + 91878, + 48465, + 48929, + 35189, + 42764, + 21194, + 41422, + 167652, + 95676, + 111961, + 26137, + 0, + 0, + 111760, + 60761, + 87645, + 85306, + 18873, + 178, + 30461, + 42843, + ] + ) # Use unweighted, because of the whole numbers (for comparison) actual = cube.as_array(weighted=False) np.testing.assert_array_equal(actual, expected) @@ -609,26 +657,113 @@ def test_mr_counts_not_pruned(): def test_mr_counts_pruned(): cube = CrunchCube(CR.PROMPTED_AWARENESS) - expected = np.array([ - 224833, 221990, 223560, 222923, 217586, 206164, 183147, 167720, - 209355, 201847, 193826, 198744, 180015, 174349, 200050, 160769, - 167969, 43193, 44339, 207539, 135973, 146002, 146789, 160692, - 53995, 95741, 135700, 91878, 48465, 48929, 35189, 42764, - 21194, 41422, 167652, 95676, 111961, 26137, 111760, 60761, - 87645, 85306, 18873, 178, 30461, 42843, - ]) + expected = np.array( + [ + 224833, + 221990, + 223560, + 222923, + 217586, + 206164, + 183147, + 167720, + 209355, + 201847, + 193826, + 198744, + 180015, + 174349, + 200050, + 160769, + 167969, + 43193, + 44339, + 207539, + 135973, + 146002, + 146789, + 160692, + 53995, + 95741, + 135700, + 91878, + 48465, + 48929, + 35189, + 42764, + 21194, + 41422, + 167652, + 95676, + 111961, + 26137, + 111760, + 60761, + 87645, + 85306, + 18873, + 178, + 30461, + 42843, + ] + ) # Use unweighted, because of the whole numbers (for comparison) actual = cube.as_array(weighted=False, prune=True) np.testing.assert_array_equal(actual[~actual.mask], expected) pruned_expected = [ np.array( - [False, False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, False, - False, False, True, True, False, False, False, False, False, - False, False, False]) + [ + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + True, + True, + False, + False, + False, + False, + False, + False, + False, + False, + ] + ) ] pruned = cube._prune_indices() assert len(pruned) == len(pruned_expected) @@ -638,24 +773,58 @@ def test_mr_counts_pruned(): def test_mr_props_not_pruned(): cube = CrunchCube(CR.PROMPTED_AWARENESS) - expected = np.array([ - 9.70083312e-01, 9.53131845e-01, 9.64703914e-01, - 9.59703205e-01, 9.37891446e-01, 8.84137923e-01, - 7.77056917e-01, 7.15135296e-01, 9.03057657e-01, - 8.67103783e-01, 8.38011719e-01, 8.60897234e-01, - 7.68101070e-01, 7.59030477e-01, 8.66127931e-01, - 6.89111039e-01, 7.39338305e-01, 1.89895586e-01, - 1.95866187e-01, 8.90452848e-01, 6.10278144e-01, - 6.35237428e-01, 6.54874171e-01, 6.89736947e-01, - 2.31607423e-01, 4.44608376e-01, 6.06987388e-01, - 4.16165746e-01, 2.06262071e-01, 2.08512519e-01, - 1.59533129e-01, 1.86245154e-01, 1.01661334e-01, - 1.82235674e-01, 7.30060936e-01, 4.45912391e-01, - 4.87037442e-01, 1.29527814e-01, 0.00000000e+00, - 0.00000000e+00, 4.95486986e-01, 2.84392427e-01, - 3.93962082e-01, 3.91279968e-01, 8.96639874e-02, - 9.50985735e-04, 1.35477929e-01, 1.86531215e-01, - ]) + expected = np.array( + [ + 9.70083312e-01, + 9.53131845e-01, + 9.64703914e-01, + 9.59703205e-01, + 9.37891446e-01, + 8.84137923e-01, + 7.77056917e-01, + 7.15135296e-01, + 9.03057657e-01, + 8.67103783e-01, + 8.38011719e-01, + 8.60897234e-01, + 7.68101070e-01, + 7.59030477e-01, + 8.66127931e-01, + 6.89111039e-01, + 7.39338305e-01, + 1.89895586e-01, + 1.95866187e-01, + 8.90452848e-01, + 6.10278144e-01, + 6.35237428e-01, + 6.54874171e-01, + 6.89736947e-01, + 2.31607423e-01, + 4.44608376e-01, + 6.06987388e-01, + 4.16165746e-01, + 2.06262071e-01, + 2.08512519e-01, + 1.59533129e-01, + 1.86245154e-01, + 1.01661334e-01, + 1.82235674e-01, + 7.30060936e-01, + 4.45912391e-01, + 4.87037442e-01, + 1.29527814e-01, + 0.00000000e00, + 0.00000000e00, + 4.95486986e-01, + 2.84392427e-01, + 3.93962082e-01, + 3.91279968e-01, + 8.96639874e-02, + 9.50985735e-04, + 1.35477929e-01, + 1.86531215e-01, + ] + ) actual = cube.proportions() np.testing.assert_almost_equal(actual, expected) @@ -664,73 +833,261 @@ def test_mr_x_cat_x_mr_pruned_rows(): cube = CrunchCube(CR.MR_X_CAT_X_MR) # Not pruned - expected = np.array([ - [4.67364825, 18.28952353, 8.07855047, 14.86987594], - [8.02124010, 17.29617716, 7.15665312, 15.44355489], - [93.6564386, 150.46443416, 96.56536588, 188.31770695], - [0., 0., 0., 0.], - ]) + expected = np.array( + [ + [4.67364825, 18.28952353, 8.07855047, 14.86987594], + [8.02124010, 17.29617716, 7.15665312, 15.44355489], + [93.6564386, 150.46443416, 96.56536588, 188.31770695], + [0.0, 0.0, 0.0, 0.0], + ] + ) actual = cube.as_array()[3] np.testing.assert_almost_equal(actual, expected) # Pruned - expected = np.array([ - [4.67364825, 18.28952353, 8.07855047, 14.86987594], - [8.02124010, 17.29617716, 7.15665312, 15.44355489], - [93.6564386, 150.46443416, 96.56536588, 188.31770695], - ]) + expected = np.array( + [ + [4.67364825, 18.28952353, 8.07855047, 14.86987594], + [8.02124010, 17.29617716, 7.15665312, 15.44355489], + [93.6564386, 150.46443416, 96.56536588, 188.31770695], + ] + ) actual = np.ma.compress_rows(cube.as_array(prune=True)[3]) np.testing.assert_almost_equal(actual, expected) def test_mr_x_num_with_means_pruned(): cube = CrunchCube(CR.BBC_NEWS) - expected = np.array([ - [38.79868092168848, 37.911460968343384, 21.566826228784073, - 28.903166828677023, np.nan, np.nan, np.nan, np.nan], - [12.361417346615546, 10.917884486901682, 8.55836343660059, - -9.233361511954936, np.nan, np.nan, np.nan, np.nan], - [25.355665361847333, -1.8732391808022093, -10.458322652141625, - -19.009325927555476, np.nan, np.nan, np.nan, np.nan], - [-1.227733208698524, -7.996716641982194, -30.95431482676578, - -18.03417096792156, np.nan, np.nan, np.nan, np.nan], - [-23.803824133140722, -26.697282878138527, -61.23218387646827, - -48.49820981263205, np.nan, np.nan, np.nan, np.nan], - [19.60453509722427, -24.876630784866492, -52.08108013616227, - 7.638330747500843, np.nan, np.nan, np.nan, np.nan], - [-26.98268155304967, -9.662317734860315, -90.91475189122735, - -46.92610737983078, np.nan, np.nan, np.nan, np.nan], - [19.45552783488183, -27.48308452819968, -62.33543385309548, - -39.83388919377415, np.nan, np.nan, np.nan, np.nan], - [20.599562677755262, 17.499111571449458, 6.299513722727599, - 2.285722391598358, np.nan, np.nan, np.nan, np.nan], - ]) + expected = np.array( + [ + [ + 38.79868092168848, + 37.911460968343384, + 21.566826228784073, + 28.903166828677023, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 12.361417346615546, + 10.917884486901682, + 8.55836343660059, + -9.233361511954936, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 25.355665361847333, + -1.8732391808022093, + -10.458322652141625, + -19.009325927555476, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -1.227733208698524, + -7.996716641982194, + -30.95431482676578, + -18.03417096792156, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -23.803824133140722, + -26.697282878138527, + -61.23218387646827, + -48.49820981263205, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 19.60453509722427, + -24.876630784866492, + -52.08108013616227, + 7.638330747500843, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -26.98268155304967, + -9.662317734860315, + -90.91475189122735, + -46.92610737983078, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 19.45552783488183, + -27.48308452819968, + -62.33543385309548, + -39.83388919377415, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 20.599562677755262, + 17.499111571449458, + 6.299513722727599, + 2.285722391598358, + np.nan, + np.nan, + np.nan, + np.nan, + ], + ] + ) actual = np.ma.compress_cols(cube.as_array(prune=True)) np.testing.assert_almost_equal(actual, expected) def test_mr_x_num_with_means_not_pruned(): cube = CrunchCube(CR.BBC_NEWS) - expected = np.array([ - [38.79868092, 37.91146097, 21.56682623, 28.90316683, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [12.36141735, 10.91788449, 8.55836344, -9.23336151, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [25.35566536, -1.87323918, -10.45832265, -19.00932593, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [-1.22773321, -7.99671664, -30.95431483, -18.03417097, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [-23.80382413, -26.69728288, -61.23218388, -48.49820981, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [19.6045351, -24.87663078, -52.08108014, 7.63833075, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [-26.98268155, -9.66231773, -90.91475189, -46.92610738, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [19.45552783, -27.48308453, -62.33543385, -39.83388919, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [20.59956268, 17.49911157, 6.29951372, 2.28572239, - np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - ]) + expected = np.array( + [ + [ + 38.79868092, + 37.91146097, + 21.56682623, + 28.90316683, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 12.36141735, + 10.91788449, + 8.55836344, + -9.23336151, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 25.35566536, + -1.87323918, + -10.45832265, + -19.00932593, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -1.22773321, + -7.99671664, + -30.95431483, + -18.03417097, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -23.80382413, + -26.69728288, + -61.23218388, + -48.49820981, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 19.6045351, + -24.87663078, + -52.08108014, + 7.63833075, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + -26.98268155, + -9.66231773, + -90.91475189, + -46.92610738, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 19.45552783, + -27.48308453, + -62.33543385, + -39.83388919, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + [ + 20.59956268, + 17.49911157, + 6.29951372, + 2.28572239, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + np.nan, + ], + ] + ) actual = cube.as_array() np.testing.assert_almost_equal(actual, expected) @@ -744,9 +1101,7 @@ def test_mr_x_num_rows_margin(): def test_mr_x_num_cols_margin_not_pruned_unweighted(): cube = CrunchCube(CR.BBC_NEWS) - expected = np.array( - [1728, 1523, 1570, 1434, 1459, 1429, 1461, 1432, 0, 0, 0, 0] - ) + expected = np.array([1728, 1523, 1570, 1434, 1459, 1429, 1461, 1432, 0, 0, 0, 0]) margin = cube.margin(axis=0, weighted=False) for actual in margin: np.testing.assert_array_equal(actual, expected) @@ -755,8 +1110,20 @@ def test_mr_x_num_cols_margin_not_pruned_unweighted(): def test_mr_x_num_cols_margin_not_pruned_weighted(): cube = CrunchCube(CR.BBC_NEWS) expected = np.array( - [1709.607711404295, 1438.5504956329391, 1556.0764946283794, - 1419.8513591680107, 0, 0, 0, 0, 0, 0, 0, 0] + [ + 1709.607711404295, + 1438.5504956329391, + 1556.0764946283794, + 1419.8513591680107, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ] ) margin = cube.margin(axis=0, weighted=True) for actual in margin: @@ -766,9 +1133,7 @@ def test_mr_x_num_cols_margin_not_pruned_weighted(): def test_mr_x_num_cols_margin_pruned_unweighted(): cube = CrunchCube(CR.BBC_NEWS) expected = np.array([1728, 1523, 1570, 1434, 1459, 1429, 1461, 1432]) - margin = np.ma.compress_cols( - cube.margin(axis=0, weighted=False, prune=True) - ) + margin = np.ma.compress_cols(cube.margin(axis=0, weighted=False, prune=True)) for actual in margin: np.testing.assert_array_equal(actual, expected) @@ -776,130 +1141,266 @@ def test_mr_x_num_cols_margin_pruned_unweighted(): def test_mr_x_num_cols_margin_pruned_weighted(): cube = CrunchCube(CR.BBC_NEWS) expected = np.array( - [1709.607711404295, 1438.5504956329391, 1556.0764946283794, - 1419.8513591680107, 0, 0, 0, 0] - ) - margin = np.ma.compress_cols( - cube.margin(axis=0, weighted=True, prune=True) + [ + 1709.607711404295, + 1438.5504956329391, + 1556.0764946283794, + 1419.8513591680107, + 0, + 0, + 0, + 0, + ] ) + margin = np.ma.compress_cols(cube.margin(axis=0, weighted=True, prune=True)) for actual in margin: np.testing.assert_array_almost_equal(actual, expected) def test_num_x_mr_props_by_row(): cube = CrunchCube(CR.AGE_X_ACCRPIPE) - expected = np.array([ - [0.33333333, 0.44444444, 0.18518519, 0.03703704], - [0.512, 0.24, 0.208, 0.04], - [0.37234043, 0.35106383, 0.21276596, 0.06382979], - [0.36956522, 0.36141304, 0.22826087, 0.04076087], - [0.32666667, 0.40888889, 0.22666667, 0.03777778], - [0.29718004, 0.42516269, 0.23210412, 0.04555315], - [0.2633833, 0.41541756, 0.27623126, 0.04496788], - [0.23193916, 0.42205323, 0.26996198, 0.07604563], - [0.25373134, 0.4212272, 0.24378109, 0.08126036], - [0.26359833, 0.41004184, 0.28242678, 0.04393305], - [0.27687296, 0.44625407, 0.21824104, 0.05863192], - [0.28571429, 0.4516129, 0.21198157, 0.05069124], - [0.29166667, 0.39583333, 0.23958333, 0.07291667], - [0.25925926, 0.40740741, 0.18518519, 0.14814815], - [0.5, 0.33333333, 0.16666667, 0.], - [0., 1., 0., 0.], - ]) + expected = np.array( + [ + [0.33333333, 0.44444444, 0.18518519, 0.03703704], + [0.512, 0.24, 0.208, 0.04], + [0.37234043, 0.35106383, 0.21276596, 0.06382979], + [0.36956522, 0.36141304, 0.22826087, 0.04076087], + [0.32666667, 0.40888889, 0.22666667, 0.03777778], + [0.29718004, 0.42516269, 0.23210412, 0.04555315], + [0.2633833, 0.41541756, 0.27623126, 0.04496788], + [0.23193916, 0.42205323, 0.26996198, 0.07604563], + [0.25373134, 0.4212272, 0.24378109, 0.08126036], + [0.26359833, 0.41004184, 0.28242678, 0.04393305], + [0.27687296, 0.44625407, 0.21824104, 0.05863192], + [0.28571429, 0.4516129, 0.21198157, 0.05069124], + [0.29166667, 0.39583333, 0.23958333, 0.07291667], + [0.25925926, 0.40740741, 0.18518519, 0.14814815], + [0.5, 0.33333333, 0.16666667, 0.0], + [0.0, 1.0, 0.0, 0.0], + ] + ) actual = np.ma.compress_rows(cube.proportions(axis=1, prune=True)) np.testing.assert_almost_equal(actual, expected) def test_num_x_mr_props_by_col(): cube = CrunchCube(CR.AGE_X_ACCRPIPE) - expected = np.array([ - [0.00707547, 0.00676437, 0.00472144, 0.00413223], - [0.05031447, 0.01691094, 0.02455146, 0.02066116], - [0.05503145, 0.03720406, 0.03777148, 0.04958678], - [0.10691824, 0.07497182, 0.07932011, 0.06198347], - [0.11556604, 0.10372041, 0.09631728, 0.07024793], - [0.1077044, 0.11048478, 0.10103872, 0.08677686], - [0.09669811, 0.10935738, 0.12181303, 0.08677686], - [0.09591195, 0.12514092, 0.13408876, 0.16528926], - [0.12028302, 0.14317926, 0.1388102, 0.20247934], - [0.0990566, 0.11048478, 0.12747875, 0.08677686], - [0.0668239, 0.07722661, 0.06326723, 0.07438017], - [0.04874214, 0.05524239, 0.0434372, 0.04545455], - [0.02201258, 0.02142052, 0.0217186, 0.02892562], - [0.00550314, 0.00620068, 0.00472144, 0.01652893], - [0.00235849, 0.0011274, 0.00094429, 0.], - [0., 0.0005637, 0., 0.], - ]) + expected = np.array( + [ + [0.00707547, 0.00676437, 0.00472144, 0.00413223], + [0.05031447, 0.01691094, 0.02455146, 0.02066116], + [0.05503145, 0.03720406, 0.03777148, 0.04958678], + [0.10691824, 0.07497182, 0.07932011, 0.06198347], + [0.11556604, 0.10372041, 0.09631728, 0.07024793], + [0.1077044, 0.11048478, 0.10103872, 0.08677686], + [0.09669811, 0.10935738, 0.12181303, 0.08677686], + [0.09591195, 0.12514092, 0.13408876, 0.16528926], + [0.12028302, 0.14317926, 0.1388102, 0.20247934], + [0.0990566, 0.11048478, 0.12747875, 0.08677686], + [0.0668239, 0.07722661, 0.06326723, 0.07438017], + [0.04874214, 0.05524239, 0.0434372, 0.04545455], + [0.02201258, 0.02142052, 0.0217186, 0.02892562], + [0.00550314, 0.00620068, 0.00472144, 0.01652893], + [0.00235849, 0.0011274, 0.00094429, 0.0], + [0.0, 0.0005637, 0.0, 0.0], + ] + ) actual = np.ma.compress_rows(cube.proportions(axis=0, prune=True)) np.testing.assert_almost_equal(actual, expected) def test_num_x_mr_props_by_cell(): cube = CrunchCube(CR.AGE_X_ACCRPIPE) - expected = np.array([ - [0.00207039, 0.00276052, 0.00115022, 0.00023004], - [0.0147228, 0.00690131, 0.00598114, 0.00115022], - [0.01610306, 0.01518288, 0.00920175, 0.00276052], - [0.03128594, 0.03059581, 0.01932367, 0.00345066], - [0.03381643, 0.04232804, 0.02346446, 0.00391074], - [0.03151599, 0.04508857, 0.02461468, 0.00483092], - [0.02829538, 0.04462848, 0.02967564, 0.00483092], - [0.02806533, 0.0510697, 0.03266621, 0.00920175], - [0.03519669, 0.0584311, 0.03381643, 0.01127214], - [0.02898551, 0.04508857, 0.0310559, 0.00483092], - [0.01955372, 0.03151599, 0.01541293, 0.00414079], - [0.01426271, 0.02254428, 0.01058201, 0.00253048], - [0.00644122, 0.00874166, 0.00529101, 0.00161031], - [0.00161031, 0.00253048, 0.00115022, 0.00092017], - [0.00069013, 0.00046009, 0.00023004, 0.], - [0., 0.00023004, 0., 0.], - ]) + expected = np.array( + [ + [0.00207039, 0.00276052, 0.00115022, 0.00023004], + [0.0147228, 0.00690131, 0.00598114, 0.00115022], + [0.01610306, 0.01518288, 0.00920175, 0.00276052], + [0.03128594, 0.03059581, 0.01932367, 0.00345066], + [0.03381643, 0.04232804, 0.02346446, 0.00391074], + [0.03151599, 0.04508857, 0.02461468, 0.00483092], + [0.02829538, 0.04462848, 0.02967564, 0.00483092], + [0.02806533, 0.0510697, 0.03266621, 0.00920175], + [0.03519669, 0.0584311, 0.03381643, 0.01127214], + [0.02898551, 0.04508857, 0.0310559, 0.00483092], + [0.01955372, 0.03151599, 0.01541293, 0.00414079], + [0.01426271, 0.02254428, 0.01058201, 0.00253048], + [0.00644122, 0.00874166, 0.00529101, 0.00161031], + [0.00161031, 0.00253048, 0.00115022, 0.00092017], + [0.00069013, 0.00046009, 0.00023004, 0.0], + [0.0, 0.00023004, 0.0, 0.0], + ] + ) actual = np.ma.compress_rows(cube.proportions(axis=None, prune=True)) np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_x_cat_missing_proportions_by_cell(): cube = CrunchCube(CR.CAT_X_MR_X_CAT_MISSING) - expected = np.array([ - [0.07211986, 0.00000000, 0.03422948, 0.10268843, 0.00000000, - 0.07184337, 0.03435395, 0.10659828, 0.07013931, 0.03422948, - 0.07171890, 0.03578536, 0.07224433], - [0.09633168, 0.07100362, 0.00000000, 0.06757349, 0.03352949, - 0.06731444, 0.03218831, 0.06425999, 0.06705898, 0.09976180, - 0.03512613, 0.03352949, 0.06757349], - [0.03223990, 0.03555871, 0.03212309, 0.06768180, 0.10100556, - 0.03223990, 0.03223990, 0.03223990, 0.09794622, 0.03223990, - 0.03212309, 0.03358323, 0.03212309], - [0.03084476, 0.06828734, 0.06462713, 0.09583320, 0.09698609, - 0.09569622, 0.03095693, 0.06498843, 0.06309156, 0.06510060, - 0.06462713, 0.06602916, 0.03224680], - [0.06891722, 0.03807479, 0.03767189, 0.11014275, 0.03452115, - 0.06904229, 0.03452115, 0.03452115, 0.10631513, 0.03452115, - 0.03767189, 0.07363141, 0.03439607], - ]) + expected = np.array( + [ + [ + 0.07211986, + 0.00000000, + 0.03422948, + 0.10268843, + 0.00000000, + 0.07184337, + 0.03435395, + 0.10659828, + 0.07013931, + 0.03422948, + 0.07171890, + 0.03578536, + 0.07224433, + ], + [ + 0.09633168, + 0.07100362, + 0.00000000, + 0.06757349, + 0.03352949, + 0.06731444, + 0.03218831, + 0.06425999, + 0.06705898, + 0.09976180, + 0.03512613, + 0.03352949, + 0.06757349, + ], + [ + 0.03223990, + 0.03555871, + 0.03212309, + 0.06768180, + 0.10100556, + 0.03223990, + 0.03223990, + 0.03223990, + 0.09794622, + 0.03223990, + 0.03212309, + 0.03358323, + 0.03212309, + ], + [ + 0.03084476, + 0.06828734, + 0.06462713, + 0.09583320, + 0.09698609, + 0.09569622, + 0.03095693, + 0.06498843, + 0.06309156, + 0.06510060, + 0.06462713, + 0.06602916, + 0.03224680, + ], + [ + 0.06891722, + 0.03807479, + 0.03767189, + 0.11014275, + 0.03452115, + 0.06904229, + 0.03452115, + 0.03452115, + 0.10631513, + 0.03452115, + 0.03767189, + 0.07363141, + 0.03439607, + ], + ] + ) actual = cube.proportions(axis=None)[0] np.testing.assert_almost_equal(actual, expected) def test_cat_x_mr_x_cat_missing_proportions_by_row(): cube = CrunchCube(CR.CAT_X_MR_X_CAT_MISSING) - expected = np.array([ - [0.10215990, 0.00000000, 0.04848706, 0.14546118, 0.00000000, - 0.10176825, 0.04866338, 0.15099960, 0.09935439, 0.04848706, - 0.10159194, 0.05069102, 0.10233622], - [0.13101878, 0.09657060, 0.00000000, 0.09190535, 0.04560278, - 0.09155302, 0.04377867, 0.08739873, 0.09120557, 0.13568403, - 0.04777434, 0.04560278, 0.09190535], - [0.05433591, 0.05992931, 0.05413904, 0.11406835, 0.17023095, - 0.05433591, 0.05433591, 0.05433591, 0.16507485, 0.05433591, - 0.05413904, 0.05659990, 0.05413904], - [0.03674991, 0.08136077, 0.07699981, 0.11418021, 0.11555381, - 0.11401700, 0.03688355, 0.07743029, 0.07517027, 0.07756393, - 0.07699981, 0.07867027, 0.03842036], - [0.09652974, 0.05332992, 0.05276559, 0.15427279, 0.04835246, - 0.09670493, 0.04835246, 0.04835246, 0.14891158, 0.04835246, - 0.05276559, 0.10313274, 0.04817727], - ]) + expected = np.array( + [ + [ + 0.10215990, + 0.00000000, + 0.04848706, + 0.14546118, + 0.00000000, + 0.10176825, + 0.04866338, + 0.15099960, + 0.09935439, + 0.04848706, + 0.10159194, + 0.05069102, + 0.10233622, + ], + [ + 0.13101878, + 0.09657060, + 0.00000000, + 0.09190535, + 0.04560278, + 0.09155302, + 0.04377867, + 0.08739873, + 0.09120557, + 0.13568403, + 0.04777434, + 0.04560278, + 0.09190535, + ], + [ + 0.05433591, + 0.05992931, + 0.05413904, + 0.11406835, + 0.17023095, + 0.05433591, + 0.05433591, + 0.05433591, + 0.16507485, + 0.05433591, + 0.05413904, + 0.05659990, + 0.05413904, + ], + [ + 0.03674991, + 0.08136077, + 0.07699981, + 0.11418021, + 0.11555381, + 0.11401700, + 0.03688355, + 0.07743029, + 0.07517027, + 0.07756393, + 0.07699981, + 0.07867027, + 0.03842036, + ], + [ + 0.09652974, + 0.05332992, + 0.05276559, + 0.15427279, + 0.04835246, + 0.09670493, + 0.04835246, + 0.04835246, + 0.14891158, + 0.04835246, + 0.05276559, + 0.10313274, + 0.04817727, + ], + ] + ) # 3D cube - hence row == 2 actual = cube.proportions(axis=2)[0] np.testing.assert_almost_equal(actual, expected) @@ -907,18 +1408,85 @@ def test_cat_x_mr_x_cat_missing_proportions_by_row(): def test_cat_x_mr_x_cat_missing_proportions_by_col(): cube = CrunchCube(CR.CAT_X_MR_X_CAT_MISSING) - expected = np.array([ - [0.67814114, np.nan, 0.47727273, 0.57668021, 0., 1., 1., 1., 1., - 0.47461929, 1., 1., 0.66874513], - [1., 1., 0., 0.50139377, 1., 1., 1., 0.64413423, 0.67567568, 1., - 0.52272727, 1., 0.50696106], - [0.24415882, 1., 0.47727273, 0.50139377, 1., 0.5, 1., 0.47552448, 1., - 1., 0.47727273, 1., 0.2406135], - [0.49909256, 1., 1., 0.73936493, 1., 1., 1., 1., 1., 1., 1., 1., - 0.25155048], - [0.64413423, 1., 1., 0.61554653, 0.47817837, 1., 1., 0.5, 1., - 0.47552448, 0.52272727, 1., 0.49909256], - ]) + expected = np.array( + [ + [ + 0.67814114, + np.nan, + 0.47727273, + 0.57668021, + 0.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.47461929, + 1.0, + 1.0, + 0.66874513, + ], + [ + 1.0, + 1.0, + 0.0, + 0.50139377, + 1.0, + 1.0, + 1.0, + 0.64413423, + 0.67567568, + 1.0, + 0.52272727, + 1.0, + 0.50696106, + ], + [ + 0.24415882, + 1.0, + 0.47727273, + 0.50139377, + 1.0, + 0.5, + 1.0, + 0.47552448, + 1.0, + 1.0, + 0.47727273, + 1.0, + 0.2406135, + ], + [ + 0.49909256, + 1.0, + 1.0, + 0.73936493, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.25155048, + ], + [ + 0.64413423, + 1.0, + 1.0, + 0.61554653, + 0.47817837, + 1.0, + 1.0, + 0.5, + 1.0, + 0.47552448, + 0.52272727, + 1.0, + 0.49909256, + ], + ] + ) # 3D cube - hence col == 1 actual = cube.proportions(axis=1)[0] np.testing.assert_almost_equal(actual, expected) @@ -926,131 +1494,341 @@ def test_cat_x_mr_x_cat_missing_proportions_by_col(): def test_cat_by_mr_hs_col_percentage(): cube = CrunchCube(CR.CAT_X_MR_HS) - expected = np.array([ - [0.44079255048452126, 0.12706996944659374, 0.02245084839681615, - 0.03842827050449689, 0.06423004017489264], - [0.19275310260052075, 0.17758354354978947, 0.15543673007827843, - 0.11799738543815302, 0.19460845018411604], - [0.6335456530850421, 0.3046535129963832, 0.1778875784750946, - 0.1564256559426499, 0.2588384903590087], - [0.0, 0.0, 0.0, 0.0, 0.0], - [0.13200554712733142, 0.35154979021049976, 0.40588130853850274, - 0.35971868142125785, 0.3444274246321915], - [0.23444879978762653, 0.3437966967931169, 0.41623111298640264, - 0.48385566263609225, 0.3967340850087999], - [0.0, 0.0, 0.0, 0.0, 0.0], - [0.36645434691495793, 0.6953464870036167, 0.8221124215249054, - 0.8435743440573501, 0.7411615096409914] - ]) + expected = np.array( + [ + [ + 0.44079255048452126, + 0.12706996944659374, + 0.02245084839681615, + 0.03842827050449689, + 0.06423004017489264, + ], + [ + 0.19275310260052075, + 0.17758354354978947, + 0.15543673007827843, + 0.11799738543815302, + 0.19460845018411604, + ], + [ + 0.6335456530850421, + 0.3046535129963832, + 0.1778875784750946, + 0.1564256559426499, + 0.2588384903590087, + ], + [0.0, 0.0, 0.0, 0.0, 0.0], + [ + 0.13200554712733142, + 0.35154979021049976, + 0.40588130853850274, + 0.35971868142125785, + 0.3444274246321915, + ], + [ + 0.23444879978762653, + 0.3437966967931169, + 0.41623111298640264, + 0.48385566263609225, + 0.3967340850087999, + ], + [0.0, 0.0, 0.0, 0.0, 0.0], + [ + 0.36645434691495793, + 0.6953464870036167, + 0.8221124215249054, + 0.8435743440573501, + 0.7411615096409914, + ], + ] + ) actual = cube.proportions(axis=0, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_cat_by_mr_hs_row_percentage(): cube = CrunchCube(CR.CAT_X_MR_HS) - expected = np.array([ - [0.6399160598631669, 0.5710629087411291, 0.23101895600507977, - 0.6728815025053523, 0.7820669403643355], - [0.18579712140082952, 0.3079658200088574, 0.47698573451339377, - 0.6856928028950228, 0.8309421217908072], - [0.3670032197169821, 0.38122252445013116, 0.4204835796699004, - 0.6825005266236387, 0.8182527171506743], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [0.07093259641440403, 0.3229818264527783, 0.5550939883964581, - 0.7966136657386232, 0.7825790252579282], - [0.1179106652004235, 0.31211928726996235, 0.510266054902361, - 0.8563898792610921, 0.799644741373273], - [np.nan, np.nan, np.nan, np.nan, np.nan], - [0.09519878824704209, 0.3175182147280742, 0.5314553657872426, - 0.8298369139048698, 0.791622434443332] - ]) + expected = np.array( + [ + [ + 0.6399160598631669, + 0.5710629087411291, + 0.23101895600507977, + 0.6728815025053523, + 0.7820669403643355, + ], + [ + 0.18579712140082952, + 0.3079658200088574, + 0.47698573451339377, + 0.6856928028950228, + 0.8309421217908072, + ], + [ + 0.3670032197169821, + 0.38122252445013116, + 0.4204835796699004, + 0.6825005266236387, + 0.8182527171506743, + ], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [ + 0.07093259641440403, + 0.3229818264527783, + 0.5550939883964581, + 0.7966136657386232, + 0.7825790252579282, + ], + [ + 0.1179106652004235, + 0.31211928726996235, + 0.510266054902361, + 0.8563898792610921, + 0.799644741373273, + ], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [ + 0.09519878824704209, + 0.3175182147280742, + 0.5314553657872426, + 0.8298369139048698, + 0.791622434443332, + ], + ] + ) actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_cat_by_mr_hs_cell_percentage(): cube = CrunchCube(CR.CAT_X_MR_HS) - expected = np.array([ - [0.07905704201278009, 0.042511244168882356, 0.011396586674371037, - 0.03084751530784915, 0.05127790466367509], - [0.03457066167210144, 0.05941055477622783, 0.07890339533757364, - 0.09472000966485485, 0.15536520805707787], - [0.11362770368488154, 0.10192179894511019, 0.09029998201194467, - 0.125567524972704, 0.20664311272075297], - [0.0, 0.0, 0.0, 0.0, 0.0], - [0.023675463829173602, 0.11761094327986822, 0.20603504288604813, - 0.28875688096249497, 0.2749728413021995], - [0.042048869914617856, 0.11501714673796347, 0.21128885073190257, - 0.388405326703676, 0.3167317431612616], - [0.0, 0.0, 0.0, 0.0, 0.0], - [0.06572433374379145, 0.2326280900178317, 0.4173238936179507, - 0.677162207666171, 0.5917045844634612] - ]) + expected = np.array( + [ + [ + 0.07905704201278009, + 0.042511244168882356, + 0.011396586674371037, + 0.03084751530784915, + 0.05127790466367509, + ], + [ + 0.03457066167210144, + 0.05941055477622783, + 0.07890339533757364, + 0.09472000966485485, + 0.15536520805707787, + ], + [ + 0.11362770368488154, + 0.10192179894511019, + 0.09029998201194467, + 0.125567524972704, + 0.20664311272075297, + ], + [0.0, 0.0, 0.0, 0.0, 0.0], + [ + 0.023675463829173602, + 0.11761094327986822, + 0.20603504288604813, + 0.28875688096249497, + 0.2749728413021995, + ], + [ + 0.042048869914617856, + 0.11501714673796347, + 0.21128885073190257, + 0.388405326703676, + 0.3167317431612616, + ], + [0.0, 0.0, 0.0, 0.0, 0.0], + [ + 0.06572433374379145, + 0.2326280900178317, + 0.4173238936179507, + 0.677162207666171, + 0.5917045844634612, + ], + ] + ) actual = cube.proportions(axis=None, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_mr_by_cat_hs_col_percentage(): cube = CrunchCube(CR.MR_X_CAT_HS) - expected = np.array([ - [0.6399160598631669, 0.18579712140082952, 0.3670032197169821, - np.nan, 0.07093259641440403, 0.1179106652004235, np.nan, - 0.09519878824704209], - [0.5710629087411291, 0.3079658200088574, 0.38122252445013116, - np.nan, 0.3229818264527783, 0.31211928726996235, np.nan, - 0.3175182147280742], - [0.23101895600507977, 0.47698573451339377, 0.4204835796699004, - np.nan, 0.5550939883964581, 0.510266054902361, np.nan, - 0.5314553657872426], - [0.6728815025053523, 0.6856928028950228, 0.6825005266236387, np.nan, - 0.7966136657386232, 0.8563898792610921, np.nan, - 0.8298369139048698], - [0.7820669403643355, 0.8309421217908072, 0.8182527171506743, np.nan, - 0.7825790252579282, 0.799644741373273, np.nan, - 0.791622434443332], - ]) + expected = np.array( + [ + [ + 0.6399160598631669, + 0.18579712140082952, + 0.3670032197169821, + np.nan, + 0.07093259641440403, + 0.1179106652004235, + np.nan, + 0.09519878824704209, + ], + [ + 0.5710629087411291, + 0.3079658200088574, + 0.38122252445013116, + np.nan, + 0.3229818264527783, + 0.31211928726996235, + np.nan, + 0.3175182147280742, + ], + [ + 0.23101895600507977, + 0.47698573451339377, + 0.4204835796699004, + np.nan, + 0.5550939883964581, + 0.510266054902361, + np.nan, + 0.5314553657872426, + ], + [ + 0.6728815025053523, + 0.6856928028950228, + 0.6825005266236387, + np.nan, + 0.7966136657386232, + 0.8563898792610921, + np.nan, + 0.8298369139048698, + ], + [ + 0.7820669403643355, + 0.8309421217908072, + 0.8182527171506743, + np.nan, + 0.7825790252579282, + 0.799644741373273, + np.nan, + 0.791622434443332, + ], + ] + ) actual = cube.proportions(axis=0, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_mr_by_cat_hs_row_percentage(): cube = CrunchCube(CR.MR_X_CAT_HS) - expected = np.array([ - [0.44079255048452126, 0.19275310260052075, 0.633545653085042, 0.0, - 0.13200554712733142, 0.23444879978762653, 0.0, - 0.366454346914958], - [0.12706996944659374, 0.17758354354978947, 0.3046535129963832, 0.0, - 0.35154979021049976, 0.3437966967931169, 0.0, - 0.6953464870036167], - [0.02245084839681615, 0.15543673007827843, 0.17788757847509457, 0.0, - 0.40588130853850274, 0.41623111298640264, 0.0, - 0.8221124215249053], - [0.03842827050449689, 0.11799738543815302, 0.1564256559426499, 0.0, - 0.35971868142125785, 0.48385566263609225, 0.0, - 0.8435743440573501], - [0.06423004017489264, 0.19460845018411604, 0.2588384903590087, 0.0, - 0.3444274246321915, 0.3967340850087999, 0.0, 0.7411615096409915] - ]) + expected = np.array( + [ + [ + 0.44079255048452126, + 0.19275310260052075, + 0.633545653085042, + 0.0, + 0.13200554712733142, + 0.23444879978762653, + 0.0, + 0.366454346914958, + ], + [ + 0.12706996944659374, + 0.17758354354978947, + 0.3046535129963832, + 0.0, + 0.35154979021049976, + 0.3437966967931169, + 0.0, + 0.6953464870036167, + ], + [ + 0.02245084839681615, + 0.15543673007827843, + 0.17788757847509457, + 0.0, + 0.40588130853850274, + 0.41623111298640264, + 0.0, + 0.8221124215249053, + ], + [ + 0.03842827050449689, + 0.11799738543815302, + 0.1564256559426499, + 0.0, + 0.35971868142125785, + 0.48385566263609225, + 0.0, + 0.8435743440573501, + ], + [ + 0.06423004017489264, + 0.19460845018411604, + 0.2588384903590087, + 0.0, + 0.3444274246321915, + 0.3967340850087999, + 0.0, + 0.7411615096409915, + ], + ] + ) actual = cube.proportions(axis=1, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) def test_mr_by_cat_hs_cell_percentage(): cube = CrunchCube(CR.MR_X_CAT_HS) - expected = np.array([ - [0.07905704201278009, 0.03457066167210144, 0.11362770368488152, 0.0, - 0.023675463829173602, 0.042048869914617856, 0.0, - 0.06572433374379145], - [0.042511244168882356, 0.05941055477622783, 0.10192179894511019, - 0.0, 0.11761094327986822, 0.11501714673796347, 0.0, - 0.2326280900178317], - [0.011396586674371037, 0.07890339533757364, 0.09029998201194467, - 0.0, 0.20603504288604813, 0.21128885073190257, 0.0, - 0.4173238936179507], - [0.03084751530784915, 0.09472000966485485, 0.125567524972704, 0.0, - 0.28875688096249497, 0.388405326703676, 0.0, 0.677162207666171], - [0.05127790466367509, 0.15536520805707787, 0.20664311272075295, 0.0, - 0.2749728413021995, 0.3167317431612616, 0.0, 0.5917045844634611] - ]) + expected = np.array( + [ + [ + 0.07905704201278009, + 0.03457066167210144, + 0.11362770368488152, + 0.0, + 0.023675463829173602, + 0.042048869914617856, + 0.0, + 0.06572433374379145, + ], + [ + 0.042511244168882356, + 0.05941055477622783, + 0.10192179894511019, + 0.0, + 0.11761094327986822, + 0.11501714673796347, + 0.0, + 0.2326280900178317, + ], + [ + 0.011396586674371037, + 0.07890339533757364, + 0.09029998201194467, + 0.0, + 0.20603504288604813, + 0.21128885073190257, + 0.0, + 0.4173238936179507, + ], + [ + 0.03084751530784915, + 0.09472000966485485, + 0.125567524972704, + 0.0, + 0.28875688096249497, + 0.388405326703676, + 0.0, + 0.677162207666171, + ], + [ + 0.05127790466367509, + 0.15536520805707787, + 0.20664311272075295, + 0.0, + 0.2749728413021995, + 0.3167317431612616, + 0.0, + 0.5917045844634611, + ], + ] + ) actual = cube.proportions(axis=None, include_transforms_for_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) diff --git a/tests/integration/test_scale_means.py b/tests/integration/test_scale_means.py index 745b35b15..fe5f5312f 100644 --- a/tests/integration/test_scale_means.py +++ b/tests/integration/test_scale_means.py @@ -10,9 +10,7 @@ def test_ca_cat_x_items(): cube = CrunchCube(SM.CA_CAT_X_ITEMS) - expected = [[ - np.array([1.50454821, 3.11233766, 3.35788192, 3.33271833]), None, - ]] + expected = [[np.array([1.50454821, 3.11233766, 3.35788192, 3.33271833]), None]] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -31,9 +29,7 @@ def test_ca_cat_x_items(): def test_ca_items_x_cat(): cube = CrunchCube(SM.CA_ITEMS_X_CAT) - expected = [[ - None, np.array([1.50454821, 3.11233766, 3.35788192, 3.33271833]), - ]] + expected = [[None, np.array([1.50454821, 3.11233766, 3.35788192, 3.33271833])]] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -106,12 +102,14 @@ def test_cat_x_ca_cat_x_items(): def test_cat_x_cat(): cube = CrunchCube(SM.CAT_X_CAT) - expected = [[ - np.array([2.6009281, 2.3522267, 2.3197279, 3.3949192]), - np.array( - [1.43636364, 2.45238095, 2.4730832, 2.68387097, 2.8375, 2.15540541] - ), - ]] + expected = [ + [ + np.array([2.6009281, 2.3522267, 2.3197279, 3.3949192]), + np.array( + [1.43636364, 2.45238095, 2.4730832, 2.68387097, 2.8375, 2.15540541] + ), + ] + ] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -183,12 +181,14 @@ def test_cat_x_cat_with_hs(): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) # Test without H&S - expected = [[ - np.array( - [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] - ), - np.array([3.87368421, 2.51767677, 3.38429752, 3.66666667, 4.13235294]), - ]] + expected = [ + [ + np.array( + [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] + ), + np.array([3.87368421, 2.51767677, 3.38429752, 3.66666667, 4.13235294]), + ] + ] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -198,14 +198,16 @@ def test_cat_x_cat_with_hs(): assert_scale_means_equal(actual, expected[0]) # Test with H&S - expected = [[ - np.array( - [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] - ), - np.array( - [3.87368421, 2.51767677, np.nan, 3.38429752, 3.66666667, 4.13235294] - ), - ]] + expected = [ + [ + np.array( + [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] + ), + np.array( + [3.87368421, 2.51767677, np.nan, 3.38429752, 3.66666667, 4.13235294] + ), + ] + ] actual = cube.scale_means(hs_dims=[0, 1]) assert_scale_means_equal(actual, expected) @@ -240,14 +242,14 @@ def test_cat_x_cat_with_hs_on_both_dims(): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_AND_COL_HS) # Test without H&S - expected = [[ - np.array( - [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] - ), - np.array( - [3.87368421, 2.51767677, 3.38429752, 3.66666667, 4.13235294] - ), - ]] + expected = [ + [ + np.array( + [2.19444444, 2.19230769, 2.26666667, 1.88990826, 1.76363636, 3.85] + ), + np.array([3.87368421, 2.51767677, 3.38429752, 3.66666667, 4.13235294]), + ] + ] actual = cube.scale_means() assert_scale_means_equal(actual, expected) @@ -256,16 +258,24 @@ def test_cat_x_cat_with_hs_on_both_dims(): assert_scale_means_equal(actual, expected[0]) # Test with H&S - expected = [[ - np.array([ - 2.19444444, 2.19230769, 2.26666667, np.nan, 1.88990826, - 1.76363636, 3.85, - ]), - np.array([ - 3.87368421, 2.51767677, np.nan, 3.38429752, 3.66666667, - 4.13235294, - ]), - ]] + expected = [ + [ + np.array( + [ + 2.19444444, + 2.19230769, + 2.26666667, + np.nan, + 1.88990826, + 1.76363636, + 3.85, + ] + ), + np.array( + [3.87368421, 2.51767677, np.nan, 3.38429752, 3.66666667, 4.13235294] + ), + ] + ] actual = cube.scale_means(hs_dims=[0, 1]) assert_scale_means_equal(actual, expected) @@ -296,39 +306,43 @@ def test_ca_x_mr_with_hs_and_pruning(): def test_cat_x_cat_pruning_and_hs(): cube = CrunchCube(CR.CAT_X_CAT_PRUNING_HS) - expected = [[ - np.array([1.57933884, 2.10618401, 2.30460074, np.nan, 2.34680135]), - np.array([1.74213625, 1.97, 2.45356177, 2.11838791, np.nan, 2.]), - ]] + expected = [ + [ + np.array([1.57933884, 2.10618401, 2.30460074, np.nan, 2.34680135]), + np.array([1.74213625, 1.97, 2.45356177, 2.11838791, np.nan, 2.0]), + ] + ] actual = cube.scale_means() # Just H&S assert_scale_means_equal(actual, expected) - expected = [[ - np.array( - [1.57933884, np.nan, 2.10618401, 2.30460074, np.nan, 2.34680135] - ), - np.array( - [1.74213625, np.nan, 1.97, 2.45356177, 2.11838791, np.nan, 2.] - ), - ]] + expected = [ + [ + np.array([1.57933884, np.nan, 2.10618401, 2.30460074, np.nan, 2.34680135]), + np.array([1.74213625, np.nan, 1.97, 2.45356177, 2.11838791, np.nan, 2.0]), + ] + ] actual = cube.scale_means(hs_dims=[0, 1]) # Just pruning assert_scale_means_equal(actual, expected) - expected = [[ - np.array([1.57933884, 2.10618401, 2.30460074, 2.34680135]), - np.array([1.74213625, 1.97, 2.45356177, 2.11838791, 2.]), - ]] + expected = [ + [ + np.array([1.57933884, 2.10618401, 2.30460074, 2.34680135]), + np.array([1.74213625, 1.97, 2.45356177, 2.11838791, 2.0]), + ] + ] actual = cube.scale_means(prune=True) assert_scale_means_equal(actual, expected) # Pruning and H&S assert_scale_means_equal(actual, expected) - expected = [[ - np.array([1.57933884, np.nan, 2.10618401, 2.30460074, 2.34680135]), - np.array([1.74213625, np.nan, 1.97, 2.45356177, 2.11838791, 2.]), - ]] + expected = [ + [ + np.array([1.57933884, np.nan, 2.10618401, 2.30460074, 2.34680135]), + np.array([1.74213625, np.nan, 1.97, 2.45356177, 2.11838791, 2.0]), + ] + ] actual = cube.scale_means(hs_dims=[0, 1], prune=True) assert_scale_means_equal(actual, expected) diff --git a/tests/integration/test_z_scores.py b/tests/integration/test_z_scores.py index b1efba56a..9884d62fb 100644 --- a/tests/integration/test_z_scores.py +++ b/tests/integration/test_z_scores.py @@ -9,101 +9,110 @@ # pylint: disable=missing-docstring, invalid-name, no-self-use class TestStandardizedResiduals(TestCase): - '''Test cr.cube implementation of Z-Scores.''' + """Test cr.cube implementation of Z-Scores.""" def test_standardized_residuals_admit_x_dept_unweighted(self): - '''Z-Scores for normal unweighted crosstab.''' + """Z-Scores for normal unweighted crosstab.""" cube = CrunchCube(CR.ADMIT_X_DEPT_UNWEIGHTED) - expected = np.array([ + expected = np.array( [ - 18.04029231, - 13.01839498, - -2.57673984, - -3.05952633, - -7.23024453, - -19.32141026, - ], - [ - -18.04029231, - -13.01839498, - 2.57673984, - 3.05952633, - 7.23024453, - 19.32141026, - ], - ]) + [ + 18.04029231, + 13.01839498, + -2.57673984, + -3.05952633, + -7.23024453, + -19.32141026, + ], + [ + -18.04029231, + -13.01839498, + 2.57673984, + 3.05952633, + 7.23024453, + 19.32141026, + ], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_admit_x_gender_weighted(self): - '''Z-Scores for normal weighted crosstab.''' + """Z-Scores for normal weighted crosstab.""" cube = CrunchCube(CR.ADMIT_X_GENDER_WEIGHTED) - expected = np.array([ - [9.42561985, -9.42561985], - [-9.42561985, 9.42561985], - ]) + expected = np.array([[9.42561985, -9.42561985], [-9.42561985, 9.42561985]]) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_selected_crosstab(self): - '''Residuals for MR x CAT unweighted.''' + """Residuals for MR x CAT unweighted.""" cube = CrunchCube(CR.SELECTED_CROSSTAB_4) - expected = np.array([ - [-10.88317888, 10.88317888], - [5.23577326, -5.23577326], - [-8.89089261, 8.89089261], - [-7.31367932, 7.31367932], - [15.39360198, -15.39360198], - [-1.15219648, 1.15219648], - ]) + expected = np.array( + [ + [-10.88317888, 10.88317888], + [5.23577326, -5.23577326], + [-8.89089261, 8.89089261], + [-7.31367932, 7.31367932], + [15.39360198, -15.39360198], + [-1.15219648, 1.15219648], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_mr_x_cat(self): - '''Residuals for MR x CAT from app.''' + """Residuals for MR x CAT from app.""" cube = CrunchCube(CR.SELECTED_CROSSTAB_ARRAY_FIRST) - expected = np.array([ - [0.80134191, -0.80134191], - [0.60455606, -0.60455606], - [-0.30884247, 0.30884247], - ]) + expected = np.array( + [ + [0.80134191, -0.80134191], + [0.60455606, -0.60455606], + [-0.30884247, 0.30884247], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_cat_x_mr(self): - '''Residuals for CAT x MR from app. + """Residuals for CAT x MR from app. The results should be the exact transposition of the results from 'test_standardized_residuals_mr_x_cat' test. - ''' + """ cube = CrunchCube(CR.SELECTED_CROSSTAB_ARRAY_LAST) - expected = np.array([ - [0.80134191, 0.60455606, -0.30884247], - [-0.80134191, -0.60455606, 0.30884247], - ]) + expected = np.array( + [ + [0.80134191, 0.60455606, -0.30884247], + [-0.80134191, -0.60455606, 0.30884247], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_mr_x_mr(self): - '''Residuals for MR x MR.''' + """Residuals for MR x MR.""" cube = CrunchCube(CR.MR_X_MR) - expected = np.array([ - [12.88418373, 0.1781302, -1.21901758, 4.15682487], - [0.1781302, 11.910822, -2.70033782, 5.69476817], - [-1.21901758, -2.70033782, 13.45338666, 9.29294984], - [4.15682487, 5.69476817, 9.29294984, 15.37981857], - ]) + expected = np.array( + [ + [12.88418373, 0.1781302, -1.21901758, 4.15682487], + [0.1781302, 11.910822, -2.70033782, 5.69476817], + [-1.21901758, -2.70033782, 13.45338666, 9.29294984], + [4.15682487, 5.69476817, 9.29294984, 15.37981857], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_standardized_residuals_mr_x_mr_heterogenous(self): - '''Residuals for MR x MR (disparate MRs).''' + """Residuals for MR x MR (disparate MRs).""" cube = CrunchCube(CR.MR_X_OTHER_MR) - expected = np.array([ - [-0.17238393, 38.51646532], - [0.10271174, -39.11229693], - [-0.26443564, -39.67503947], - ]) + expected = np.array( + [ + [-0.17238393, 38.51646532], + [0.10271174, -39.11229693], + [-0.26443564, -39.67503947], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) @@ -111,18 +120,50 @@ def test_std_res_with_hs(self): cube = CrunchCube(CR.ECON_BLAME_X_IDEOLOGY_ROW_HS) # Don't include H&S dim (the one with transform) - expected = np.array([ - [-4.76107671, -6.89997234, -3.93535518, 8.76458713, 7.95483156, - -1.58387062], - [7.6019656, 10.00457686, 1.74406524, -9.01760367, -6.54691501, - -4.58037582], - [-3.27515041, -2.90214798, 2.74136144, 2.51726734, -0.1650683, - -1.77262166], - [0.89649209, -0.10100532, -1.06236896, -0.3090285, -0.86520876, - 3.67095238], - [-0.92734884, -2.08565946, -0.66824935, -2.39155976, -1.00345445, - 13.61755117], - ]) + expected = np.array( + [ + [ + -4.76107671, + -6.89997234, + -3.93535518, + 8.76458713, + 7.95483156, + -1.58387062, + ], + [ + 7.6019656, + 10.00457686, + 1.74406524, + -9.01760367, + -6.54691501, + -4.58037582, + ], + [ + -3.27515041, + -2.90214798, + 2.74136144, + 2.51726734, + -0.1650683, + -1.77262166, + ], + [ + 0.89649209, + -0.10100532, + -1.06236896, + -0.3090285, + -0.86520876, + 3.67095238, + ], + [ + -0.92734884, + -2.08565946, + -0.66824935, + -2.39155976, + -1.00345445, + 13.61755117, + ], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) @@ -130,19 +171,51 @@ def test_std_res_with_hs(self): np.testing.assert_almost_equal(actual, expected) # Include H&S (expect additional row of all zeros) - expected = np.array([ - [-4.76107671, -6.89997234, -3.93535518, 8.76458713, 7.95483156, - -1.58387062], - [7.6019656, 10.00457686, 1.74406524, -9.01760367, -6.54691501, - -4.58037582], - [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], - [-3.27515041, -2.90214798, 2.74136144, 2.51726734, -0.1650683, - -1.77262166], - [0.89649209, -0.10100532, -1.06236896, -0.3090285, -0.86520876, - 3.67095238], - [-0.92734884, -2.08565946, -0.66824935, -2.39155976, -1.00345445, - 13.61755117], - ]) + expected = np.array( + [ + [ + -4.76107671, + -6.89997234, + -3.93535518, + 8.76458713, + 7.95483156, + -1.58387062, + ], + [ + 7.6019656, + 10.00457686, + 1.74406524, + -9.01760367, + -6.54691501, + -4.58037582, + ], + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + [ + -3.27515041, + -2.90214798, + 2.74136144, + 2.51726734, + -0.1650683, + -1.77262166, + ], + [ + 0.89649209, + -0.10100532, + -1.06236896, + -0.3090285, + -0.86520876, + 3.67095238, + ], + [ + -0.92734884, + -2.08565946, + -0.66824935, + -2.39155976, + -1.00345445, + 13.61755117, + ], + ] + ) actual = cube.zscore(hs_dims=[0, 1]) np.testing.assert_almost_equal(actual, expected) @@ -151,82 +224,103 @@ def test_std_res_with_hs(self): def test_3d_z_score(self): cube = CrunchCube(CR.CA_X_MR_SIG_TESTING_SUBTOTALS) - expected = np.array([ - [[-0.97184831, 0.48259011, -0.22320406, 1.90369568, 0.84276015], - [5.73141167, -2.36476938, -3.08927542, -5.58099225, -0.43365468], - [-0.19454649, 1.67287623, 3.52023931, 4.06157819, -1.46455273], - [-3.51318583, -0.57798682, -1.48960709, -3.60500408, 0.73879457]], - - [[4.36886643, 0.4898096, -2.79475924, -1.67637129, 0.45868614], - [-1.7697398, -1.64251181, -1.18172874, 1.13980645, 1.48562001], - [0.74453913, 1.41129291, 4.51918293, 2.44542304, -4.65650512], - [-2.1434799, 0.02197845, -2.83315628, -4.08730972, 3.11108133]], - - [[2.99534716, 0.18812169, -1.55495526, -3.8775711, -1.65892496], - [0.78341231, -1.37933059, -1.36159789, 1.27468504, 2.41276199], - [0.18754893, 2.15035285, 4.19074561, 2.7168425, -3.1400203], - [-3.33614118, -0.7832844, -2.3400954, -2.8017063, 1.13412111]], - - [[5.49914879, -0.8250958, 0.47711643, -2.35340835, 0.75708154], - [-0.37181993, -1.00626148, -2.51096895, 1.88779512, 0.99337053], - [0.12820659, 1.15156133, 3.49017797, 1.11329826, -4.44156835], - [-3.09836263, 0.31537683, -1.41949801, -2.77042193, 3.19138838]], - ]) + expected = np.array( + [ + [ + [-0.97184831, 0.48259011, -0.22320406, 1.90369568, 0.84276015], + [5.73141167, -2.36476938, -3.08927542, -5.58099225, -0.43365468], + [-0.19454649, 1.67287623, 3.52023931, 4.06157819, -1.46455273], + [-3.51318583, -0.57798682, -1.48960709, -3.60500408, 0.73879457], + ], + [ + [4.36886643, 0.4898096, -2.79475924, -1.67637129, 0.45868614], + [-1.7697398, -1.64251181, -1.18172874, 1.13980645, 1.48562001], + [0.74453913, 1.41129291, 4.51918293, 2.44542304, -4.65650512], + [-2.1434799, 0.02197845, -2.83315628, -4.08730972, 3.11108133], + ], + [ + [2.99534716, 0.18812169, -1.55495526, -3.8775711, -1.65892496], + [0.78341231, -1.37933059, -1.36159789, 1.27468504, 2.41276199], + [0.18754893, 2.15035285, 4.19074561, 2.7168425, -3.1400203], + [-3.33614118, -0.7832844, -2.3400954, -2.8017063, 1.13412111], + ], + [ + [5.49914879, -0.8250958, 0.47711643, -2.35340835, 0.75708154], + [-0.37181993, -1.00626148, -2.51096895, 1.88779512, 0.99337053], + [0.12820659, 1.15156133, 3.49017797, 1.11329826, -4.44156835], + [-3.09836263, 0.31537683, -1.41949801, -2.77042193, 3.19138838], + ], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_3d_z_score_with_mr_as_row(self): cube = CrunchCube(CR.STARTTIME_X_NORDIC_COUNTRIES_X_FOOD_GROOPS) - expected = np.array([ - [[-0.59209185, -1.38186211, -0.61880093, 2.76977489], - [-0.27226001, -0.90729991, 1.19984516, 0.18320768], - [-0.98437766, -1.06099892, 0.00862638, 2.02551167], - [-2.69271055, -0.70247291, 0.97731075, 2.35431028], - [2.14156799, -0.26884, -0.28051055, -1.62988758]], - - [[0.44613504, 3.10078541, -1.85754165, -1.95161161], - [1.47682121, -0.6300945, -1.37772587, 0.71037862], - [-1.94913113, -1.85068411, -1.08041003, 4.04917418], - [-1.06337882, -0.82946295, -0.13656886, 1.73737263], - [3.08099203, 0.23633954, -2.13326401, -1.40411192]], - - [[-0.51632005, -0.60341324, 1.08349741, 0.19639231], - [-1.10735911, -0.61498431, 0.48664175, 1.19660131], - [-0.65940873, 1.51305134, 0.17963641, -1.19850121], - [-1.89200746, 1.14283138, -1.54202798, 1.44133862], - [2.41917846, -3.08798247, 1.53524725, -1.16466106]], - - [[-1.09404899, -1.27933801, np.nan, 2.80467961], - [0.56389782, -1.94631489, 1.32101442, 0.54469167], - [np.nan, np.nan, np.nan, np.nan], - [0.9635808, -0.95595127, np.nan, 0.09616004], - [-0.78237941, 1.48226192, np.nan, -0.70605851]], - ]) + expected = np.array( + [ + [ + [-0.59209185, -1.38186211, -0.61880093, 2.76977489], + [-0.27226001, -0.90729991, 1.19984516, 0.18320768], + [-0.98437766, -1.06099892, 0.00862638, 2.02551167], + [-2.69271055, -0.70247291, 0.97731075, 2.35431028], + [2.14156799, -0.26884, -0.28051055, -1.62988758], + ], + [ + [0.44613504, 3.10078541, -1.85754165, -1.95161161], + [1.47682121, -0.6300945, -1.37772587, 0.71037862], + [-1.94913113, -1.85068411, -1.08041003, 4.04917418], + [-1.06337882, -0.82946295, -0.13656886, 1.73737263], + [3.08099203, 0.23633954, -2.13326401, -1.40411192], + ], + [ + [-0.51632005, -0.60341324, 1.08349741, 0.19639231], + [-1.10735911, -0.61498431, 0.48664175, 1.19660131], + [-0.65940873, 1.51305134, 0.17963641, -1.19850121], + [-1.89200746, 1.14283138, -1.54202798, 1.44133862], + [2.41917846, -3.08798247, 1.53524725, -1.16466106], + ], + [ + [-1.09404899, -1.27933801, np.nan, 2.80467961], + [0.56389782, -1.94631489, 1.32101442, 0.54469167], + [np.nan, np.nan, np.nan, np.nan], + [0.9635808, -0.95595127, np.nan, 0.09616004], + [-0.78237941, 1.48226192, np.nan, -0.70605851], + ], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) def test_3d_z_score_with_mr_as_col(self): cube = CrunchCube(CR.FOOD_GROOPS_X_STARTTIME_X_NORDIC_COUNTRIES) - expected = np.array([ - [[0.01506113, -0.7584501, -0.02786318, -0.31878531, 0.47399192], - [-0.11623796, 1.1295313, 0.42710872, 1.34964387, -1.01589615], - [0.60343328, -1.01855773, 0.17035643, -1.87610542, 1.79957599], - [-0.68273333, 0.46006786, -1.32308749, -0.13319154, -1.83163132]], - - [[-1.13060031, -0.164368, -0.7420848, 0.67712838, 0.21226447], - [1.06695989, 0.44796674, 0.22470228, -0.03843031, 0.10441562], - [0.40930073, 0.23774307, 1.63921143, 0.39261527, -1.31335519], - [-0.86324397, -1.34517767, -1.6837454, -2.67317279, 1.25300357]], - - [[0.43001972, 1.3126165, -0.10717325, 1.50608056, 0.65586374], - [-2.54392682, -1.99840816, -0.0500687, -0.53201525, -1.92602265], - [3.30777899, 0.76234711, 0.24895137, -2.36576364, 2.17004946], - [np.nan, 1.38291283, np.nan, np.nan, np.nan]], - - [[2.99977078, -0.32043235, -0.34165324, 1.89240508, -0.27546776], - [-4.26735077, -0.58829315, 1.92992202, -1.05792001, 0.03639644], - [1.15068951, 1.01695401, -2.17562799, -0.58087799, 0.4756435], - [2.88459281, 0.44900385, -1.83002841, -1.48069796, -0.19880727]], - ]) + expected = np.array( + [ + [ + [0.01506113, -0.7584501, -0.02786318, -0.31878531, 0.47399192], + [-0.11623796, 1.1295313, 0.42710872, 1.34964387, -1.01589615], + [0.60343328, -1.01855773, 0.17035643, -1.87610542, 1.79957599], + [-0.68273333, 0.46006786, -1.32308749, -0.13319154, -1.83163132], + ], + [ + [-1.13060031, -0.164368, -0.7420848, 0.67712838, 0.21226447], + [1.06695989, 0.44796674, 0.22470228, -0.03843031, 0.10441562], + [0.40930073, 0.23774307, 1.63921143, 0.39261527, -1.31335519], + [-0.86324397, -1.34517767, -1.6837454, -2.67317279, 1.25300357], + ], + [ + [0.43001972, 1.3126165, -0.10717325, 1.50608056, 0.65586374], + [-2.54392682, -1.99840816, -0.0500687, -0.53201525, -1.92602265], + [3.30777899, 0.76234711, 0.24895137, -2.36576364, 2.17004946], + [np.nan, 1.38291283, np.nan, np.nan, np.nan], + ], + [ + [2.99977078, -0.32043235, -0.34165324, 1.89240508, -0.27546776], + [-4.26735077, -0.58829315, 1.92992202, -1.05792001, 0.03639644], + [1.15068951, 1.01695401, -2.17562799, -0.58087799, 0.4756435], + [2.88459281, 0.44900385, -1.83002841, -1.48069796, -0.19880727], + ], + ] + ) actual = cube.zscore() np.testing.assert_almost_equal(actual, expected) diff --git a/tests/unit/test_crunch_cube.py b/tests/unit/test_crunch_cube.py index e6487e34f..735a27638 100644 --- a/tests/unit/test_crunch_cube.py +++ b/tests/unit/test_crunch_cube.py @@ -8,24 +8,32 @@ from unittest import TestCase from cr.cube.crunch_cube import ( - _BaseMeasure, CrunchCube, _MeanMeasure, _Measures, - _UnweightedCountMeasure, _WeightedCountMeasure + _BaseMeasure, + CrunchCube, + _MeanMeasure, + _Measures, + _UnweightedCountMeasure, + _WeightedCountMeasure, ) from cr.cube.dimension import AllDimensions, _ApparentDimensions, Dimension from cr.cube.enum import DIMENSION_TYPE as DT from ..unitutil import ( - class_mock, function_mock, instance_mock, method_mock, Mock, patch, - property_mock + class_mock, + function_mock, + instance_mock, + method_mock, + Mock, + patch, + property_mock, ) class DescribeCrunchCube(object): - def it_provides_a_default_repr(self): cube = CrunchCube(None) repr_ = repr(cube) - assert repr_.startswith('' + assert repr_ == "" def it_provides_a_user_friendly_str_representation(self): - dimension_type = _DimensionType('QUANTUM_MANIFOLD') + dimension_type = _DimensionType("QUANTUM_MANIFOLD") str_ = str(dimension_type) - assert str_ == 'DIMENSION_TYPE.QUANTUM_MANIFOLD' + assert str_ == "DIMENSION_TYPE.QUANTUM_MANIFOLD" def it_knows_its_name(self): - dimension_type = _DimensionType('WORM_HOLE') + dimension_type = _DimensionType("WORM_HOLE") name = dimension_type.name - assert name == 'WORM_HOLE' + assert name == "WORM_HOLE" diff --git a/tests/unit/test_index_table.py b/tests/unit/test_index_table.py index c0273a9d7..da650a5f7 100644 --- a/tests/unit/test_index_table.py +++ b/tests/unit/test_index_table.py @@ -1,4 +1,4 @@ -'''Unit tests for the index functionality.''' +"""Unit tests for the index functionality.""" # pylint: disable=missing-docstring, invalid-name, redefined-outer-name @@ -15,18 +15,22 @@ def test_index_performs_correct_division(index_fixture): np.testing.assert_almost_equal(actual, expected) -@pytest.fixture(params=[ - ( - [[0.714285714286, 0.285714285714], [0.625, 0.375]], - 1, [0.6, 0.4], - [[119.047619047619, 71.4285714285714], [104.16666666666667, 93.75]], - ), - ( - [[0.5, 0.4], [0.5, 0.6]], - 0, [0.6, 0.4], - [[83.3333333333333, 66.6666666666667], [125, 150]], - ), -]) +@pytest.fixture( + params=[ + ( + [[0.714285714286, 0.285714285714], [0.625, 0.375]], + 1, + [0.6, 0.4], + [[119.047619047619, 71.4285714285714], [104.16666666666667, 93.75]], + ), + ( + [[0.5, 0.4], [0.5, 0.6]], + 0, + [0.6, 0.4], + [[83.3333333333333, 66.6666666666667], [125, 150]], + ), + ] +) def index_fixture(request): proportions, axis, base, expected = request.param cc = Mock() diff --git a/tests/unit/test_scale_means.py b/tests/unit/test_scale_means.py index 4db11e2c0..7b5a8971e 100644 --- a/tests/unit/test_scale_means.py +++ b/tests/unit/test_scale_means.py @@ -33,23 +33,32 @@ def test_inflate(inflate_fixture): assert scale_means._inflate(dim_ind) == expected -@pytest.fixture(params=[ - ( - [None, ROWS_DIM_VALUES], margin, 0, 2, - np.sum(COL_MARGIN * ROWS_DIM_VALUES) / np.sum(COL_MARGIN), - ), - ( - [COLS_DIM_VALUES, None], margin, 1, 2, - np.sum(ROW_MARGIN * COLS_DIM_VALUES) / np.sum(ROW_MARGIN), - ), - ( - [None, ROWS_DIM_VALUES], margin, 0, 2, - np.sum(COL_MARGIN * ROWS_DIM_VALUES) / np.sum(COL_MARGIN), - ), - ( - [None, None], margin, 0, 2, None, - ), -]) +@pytest.fixture( + params=[ + ( + [None, ROWS_DIM_VALUES], + margin, + 0, + 2, + np.sum(COL_MARGIN * ROWS_DIM_VALUES) / np.sum(COL_MARGIN), + ), + ( + [COLS_DIM_VALUES, None], + margin, + 1, + 2, + np.sum(ROW_MARGIN * COLS_DIM_VALUES) / np.sum(ROW_MARGIN), + ), + ( + [None, ROWS_DIM_VALUES], + margin, + 0, + 2, + np.sum(COL_MARGIN * ROWS_DIM_VALUES) / np.sum(COL_MARGIN), + ), + ([None, None], margin, 0, 2, None), + ] +) def scale_means_fixture(request, values_prop_): values, margin, axis, ndim, expected = request.param values_prop_.return_value = values @@ -62,15 +71,17 @@ def scale_means_fixture(request, values_prop_): @pytest.fixture def values_prop_(request): - return property_mock(request, ScaleMeans, 'values') + return property_mock(request, ScaleMeans, "values") -@pytest.fixture(params=[ - (0, 2, (Mock(), Mock()), True), - (1, 2, (Mock(), Mock()), False), - (0, 2, (Mock(),), False), - (0, 1, (Mock(),), False), -]) +@pytest.fixture( + params=[ + (0, 2, (Mock(), Mock()), True), + (1, 2, (Mock(), Mock()), False), + (0, 2, (Mock(),), False), + (0, 1, (Mock(),), False), + ] +) def inflate_fixture(request): dim_ind, ndim, shape, expected = request.param slice_ = Mock() @@ -86,21 +97,24 @@ def test_valid_indices(valid_indices_fixture): np.testing.assert_equal(actual, expected) -@pytest.fixture(params=[ - ([Mock(numeric_values=[])], 0, []), - ([Mock(numeric_values=[1, 2, 3])], 0, [np.array([True, True, True])]), - ( - [Mock(numeric_values=[1, 2, np.nan, 4])], 0, - [np.array([True, True, False, True])], - ), - ([Mock(numeric_values=[1])], 0, []), - ( - [Mock(numeric_values=[1, 2, 3]), Mock(numeric_values=[])], 0, - [np.array([True, True, True])], - ), - ([Mock(numeric_values=[1, 2, 3]), Mock(numeric_values=[])], 1, - [slice(None)]), -]) +@pytest.fixture( + params=[ + ([Mock(numeric_values=[])], 0, []), + ([Mock(numeric_values=[1, 2, 3])], 0, [np.array([True, True, True])]), + ( + [Mock(numeric_values=[1, 2, np.nan, 4])], + 0, + [np.array([True, True, False, True])], + ), + ([Mock(numeric_values=[1])], 0, []), + ( + [Mock(numeric_values=[1, 2, 3]), Mock(numeric_values=[])], + 0, + [np.array([True, True, True])], + ), + ([Mock(numeric_values=[1, 2, 3]), Mock(numeric_values=[])], 1, [slice(None)]), + ] +) def valid_indices_fixture(request): dimensions, axis, expected = request.param slice_ = Mock() diff --git a/tests/unit/test_util.py b/tests/unit/test_util.py index 3c223d581..7cd448236 100644 --- a/tests/unit/test_util.py +++ b/tests/unit/test_util.py @@ -2,9 +2,7 @@ """Unit test suite for cr.cube.util module.""" -from __future__ import ( - absolute_import, division, print_function, unicode_literals -) +from __future__ import absolute_import, division, print_function, unicode_literals import numpy as np import pytest @@ -13,7 +11,6 @@ class Describe_compress_pruned(object): - def it_returns_an_unmasked_array_unchanged(self): table = np.zeros((2, 2)) return_value = compress_pruned(table) @@ -25,25 +22,19 @@ def it_returns_the_data_of_a_0D_masked_array(self): assert return_value == 42 def it_returns_a_compressed_1D_masked_array(self): - table = np.ma.masked_array( - np.array([42, 43, 44]), [False, True, False] - ) + table = np.ma.masked_array(np.array([42, 43, 44]), [False, True, False]) return_value = compress_pruned(table) np.testing.assert_array_equal(return_value, [42, 44]) def it_NaNs_isolated_pruned_float_values(self): table = np.ma.masked_array( - np.array([[4.2, 0.0, 4.4], - [4.5, 4.6, 4.7]]), - [[False, True, False], - [False, False, False]], - dtype=float + np.array([[4.2, 0.0, 4.4], [4.5, 4.6, 4.7]]), + [[False, True, False], [False, False, False]], + dtype=float, ) return_value = compress_pruned(table) np.testing.assert_array_equal( - return_value, - [[4.2, np.nan, 4.4], - [4.5, 4.6, 4.7]] + return_value, [[4.2, np.nan, 4.4], [4.5, 4.6, 4.7]] ) @@ -54,14 +45,14 @@ def it_is_a_lazyproperty_object_on_class_access(self, Obj): assert isinstance(Obj.fget, lazyproperty) def but_it_adopts_the_name_of_the_decorated_method(self, Obj): - assert Obj.fget.__name__ == 'fget' + assert Obj.fget.__name__ == "fget" def and_it_adopts_the_module_of_the_decorated_method(self, Obj): # ---the module name actually, not a module object assert Obj.fget.__module__ == __name__ def and_it_adopts_the_docstring_of_the_decorated_method(self, Obj): - assert Obj.fget.__doc__ == 'Docstring of Obj.fget method definition.' + assert Obj.fget.__doc__ == "Docstring of Obj.fget method definition." def it_only_calculates_value_on_first_call(self, obj): assert obj.fget == 1 @@ -82,10 +73,11 @@ class Obj(object): @lazyproperty def fget(self): """Docstring of Obj.fget method definition.""" - if not hasattr(self, '_n'): + if not hasattr(self, "_n"): self._n = 0 self._n += 1 return self._n + return Obj @pytest.fixture diff --git a/tests/unitutil.py b/tests/unitutil.py index c8e46bde3..273fa6e86 100644 --- a/tests/unitutil.py +++ b/tests/unitutil.py @@ -2,9 +2,7 @@ """Functions that make mocking with pytest easier and more readable.""" -from __future__ import ( - absolute_import, division, print_function, unicode_literals -) +from __future__ import absolute_import, division, print_function, unicode_literals from mock import ANY, call, Mock # noqa from mock import create_autospec, patch, PropertyMock @@ -22,8 +20,9 @@ def class_mock(request, q_class_name, autospec=True, **kwargs): return _patch.start() -def function_mock(request, q_function_name, autospec=True, - **kwargs): # pragma: no cover +def function_mock( + request, q_function_name, autospec=True, **kwargs +): # pragma: no cover """Return mock patching function with qualified name *q_function_name*. Patch is reversed after calling test returns. @@ -39,7 +38,7 @@ def initializer_mock(request, cls, autospec=True, **kwargs): The patch is reversed after pytest uses it. """ _patch = patch.object( - cls, '__init__', autospec=autospec, return_value=None, **kwargs + cls, "__init__", autospec=autospec, return_value=None, **kwargs ) request.addfinalizer(_patch.stop) return _patch.start() @@ -54,9 +53,7 @@ def instance_mock(request, cls, name=None, spec_set=True, **kwargs): through to the Mock() call that creates the mock. """ name = name if name is not None else request.fixturename - return create_autospec( - cls, _name=name, spec_set=spec_set, instance=True, **kwargs - ) + return create_autospec(cls, _name=name, spec_set=spec_set, instance=True, **kwargs) def method_mock(request, cls, method_name, autospec=True, **kwargs):