def setup_stack_Example_Data_A(self, name=None, fk=None, xk=None, yk=None, views=None, weights=None): if name is None: name = "Example Data (A)" if fk is None: fk = ['no_filter'] if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default'] if not isinstance(weights, list): weights = [weights] stack = Stack(name=name) stack.add_data( data_key=stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data ) for weight in weights: stack.add_link( data_keys=stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight ) return stack
def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'cbase', 'counts', 'c%'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data(data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data) for weight in weights: self.stack.add_link(data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight)
def get_stack_Example_Data_A(self, name=None, fk=None, xk=None, yk=None, views=None, weights=None): if name is None: name = 'Example Data (A)' if fk is None: fk = ['no_filter'] if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'counts'] if weights is None: weights = self.weights stack = Stack(name=name) stack.add_data( data_key=stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data ) for weight in weights: stack.add_link( data_keys=stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weights ) return stack
def setUp(self): self.path = './tests/' # self.path = '' self.filepath = '%sengine_B_data.csv' % (self.path) self.metapath = '%sengine_B_meta.json' % (self.path) self.stack = Stack("StackName") self.stack.seperator = ',' self.stack.decoding = "UTF-8" self.data = pd.DataFrame.from_csv(self.filepath) self.meta = load_json(self.metapath) self.stack.add_data(data_key="Jan", meta=self.meta, data=self.data) # self.x_names=['age', 'cost_breakfast', 'age_group', 'endtime', 'name', 'q4'], self.x_names = ['age', 'cost_breakfast', 'age_group', 'q4'] # self._types = ['int', 'float', 'single', 'date', 'string', 'delimited set'] self.x_types = ['int', 'float', 'single', 'delimited set'] self.y_names = ['profile_gender']
def get_stack_Example_Data_A(self, name=None, fk=None, xk=None, yk=None, views=None, weights=None): if name is None: name = 'Example Data (A)' if fk is None: fk = ['no_filter'] if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'counts'] if weights is None: weights = self.weights stack = Stack(name=name) stack.add_data(data_key=stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data) for weight in weights: stack.add_link(data_keys=stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weights) return stack
class TestChainObject(unittest.TestCase): def setUp(self): self.path = './tests/' self.path_chain = './temp.chain'.format(self.path) # self.path = '' project_name = 'Example Data (A)' # Load Example Data (A) data and meta into self name_data = '%s.csv' % (project_name) path_data = '%s%s' % (self.path, name_data) self.example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (self.path, name_meta) self.example_data_A_meta = load_json(path_meta) # The minimum list of variables required to populate a stack with all single*delimited set variations self.minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] self.setup_stack_Example_Data_A() self.setup_chains_Example_Data_A() def test_save_chain(self): self.setup_chains_Example_Data_A() for chain in self.chains: # Create a dictionary with the attribute structure of the chain chain_attributes = chain.__dict__ chain_described = chain.describe() # Save and then load a copy of the chain chain.save(path=self.path_chain) loaded_chain = Chain.load(self.path_chain) # Ensure that we are not comparing the same variable (in memory) self.assertNotEqual(id(chain), id(loaded_chain)) # Create a dictionary with the attribute structure of the chain loaded_chain_attributes = loaded_chain.__dict__ loaded_chain_described = loaded_chain.describe() # Confirm that the chains contain the same views sort_order = ['data', 'filter', 'x', 'y', 'view'] actual = chain_described.sort(sort_order).values.tolist() expected = loaded_chain_described.sort(sort_order).values.tolist() self.assertSequenceEqual(actual, expected) # Make sure that this is working by altering the loaded_stack_attributes # and comparing the result. (It should fail) # Change a 'value' in the dict loaded_chain_attributes['name'] = 'SomeOtherName' with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value loaded_chain_attributes['name'] = chain_attributes['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Change a 'key' in the dict del loaded_chain_attributes['name'] loaded_chain_attributes['new_name'] = chain_attributes['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value del loaded_chain_attributes['new_name'] loaded_chain_attributes['name'] = chain_attributes['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Remove a key/value pair del loaded_chain_attributes['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # Cleanup if os.path.exists('./tests/{0}.chain'.format(chain.name)): os.remove('./tests/{0}.chain'.format(chain.name)) def test_auto_orientation(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # If multiple x and y keys are given without orient_on # x-orientation chains are assumed. chain = self.stack.get_chain(name='y', data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=views) self.assertTrue(chain.orientation == 'x') def test_lazy_name(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # get chain but do not name - y orientation chain_y = self.stack.get_chain(data_keys=self.stack.name, filters=fk, x=xk, y=yk[0], views=views) # get chain but do not name - x orientation chain_x = self.stack.get_chain(data_keys=self.stack.name, filters=fk, x=xk[0], y=yk, views=views) # check lazy_name is working as it should be self.assertEqual(chain_y.name, '[email protected]_1.cbase.counts.c%') self.assertEqual(chain_x.name, '[email protected]_1.cbase.counts.c%') def test_dervie_attributes(self): # check chain attributes self.assertEqual(self.chains[0].name, '@') self.assertEqual(self.chains[0].orientation, 'y') self.assertEqual(self.chains[0].source_name, '@') self.assertEqual(self.chains[0].len_of_axis, 5) self.assertEqual(self.chains[0].content_of_axis, ['q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[0].views, ['x|f|x:|||cbase', 'x|f|:|||counts', 'x|f|:|y||c%']) self.assertEqual(self.chains[0].data_key, 'Example Data (A)') self.assertEqual(self.chains[0].filter, 'no_filter') self.assertEqual(self.chains[0].source_type, None) self.assertEqual(self.chains[-1].name, 'q5_1') self.assertEqual(self.chains[-1].orientation, 'x') self.assertEqual(self.chains[-1].source_name, 'q5_1') self.assertEqual(self.chains[-1].len_of_axis, 6) self.assertEqual(self.chains[-1].content_of_axis, ['@', 'q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[-1].views, ['x|f|x:|||cbase', 'x|f|:|||counts', 'x|f|:|y||c%']) self.assertEqual(self.chains[-1].data_key, 'Example Data (A)') self.assertEqual(self.chains[-1].filter, 'no_filter') self.assertEqual(self.chains[-1].source_type, None) def test_describe(self): fk = 'no_filter' for chain in self.chains: chain_described = chain.describe() #test describe() returns a dataframe self.assertIsInstance(chain_described, pd.DataFrame) #test descibe() returns the expected dataframe - *no args* if chain.orientation == 'y': keys = chain[self.stack.name][fk].keys() views = chain[self.stack.name][fk][keys[0]][ chain.source_name].keys() data = [self.stack.name] * (len(keys) * len(views)) filters = [fk] * (len(keys) * len(views)) x = [] for key in keys: x.extend([key] * len(views)) y = [chain.source_name] * (len(keys) * len(views)) view = [v for v in views] * len(keys) ones = [1] * (len(keys) * len(views)) df = pd.DataFrame({ 'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones }) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) elif chain.orientation == 'x': keys = chain[self.stack.name][fk][chain.source_name].keys() views = chain[self.stack.name][fk][chain.source_name][ keys[0]].keys() data = [self.stack.name] * (len(keys) * len(views)) filters = [fk] * (len(keys) * len(views)) y = [] for key in keys: y.extend([key] * len(views)) x = [chain.source_name] * (len(keys) * len(views)) view = [v for v in views] * len(keys) ones = [1] * (len(keys) * len(views)) df = pd.DataFrame({ 'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones }) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) @classmethod def tearDownClass(self): self.stack = Stack("StackName") filepath = './tests/' + self.stack.name + '.stack' if os.path.exists(filepath): os.remove(filepath) def is_empty(self, any_structure): if any_structure: #print('Structure is not empty.') return False else: #print('Structure is empty.') return True def create_key_stack(self, branch_pos="data"): """ Creates a dictionary that has the structure of the keys in the Stack It is used to loop through the stack without affecting it. """ key_stack = {} for data_key in self.stack: key_stack[data_key] = {} for the_filter in self.stack[data_key][branch_pos]: key_stack[data_key][the_filter] = {} for x in self.stack[data_key][branch_pos][the_filter]: key_stack[data_key][the_filter][x] = [] for y in self.stack[data_key][branch_pos][the_filter][x]: link = self.stack[data_key][branch_pos][the_filter][x][ y] if not isinstance(link, Link): continue key_stack[data_key][the_filter][x].append(y) return key_stack def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'cbase', 'counts', 'c%'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data(data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data) for weight in weights: self.stack.add_link(data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight) def setup_chains_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, orient_on=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['x|f|x:|||cbase', 'x|f|:|||counts', 'x|f|:|y||c%'] self.chains = [] for y in yk: self.chains.append( self.stack.get_chain(name=y, data_keys=self.stack.name, filters='no_filter', x=xk, y=y, views=views)) for x in xk: self.chains.append( self.stack.get_chain(name=x, data_keys=self.stack.name, filters='no_filter', x=x, y=yk, views=views))
def tearDownClass(self): self.stack = Stack("StackName") filepath ='./tests/'+self.stack.name+'.stack' if os.path.exists(filepath): os.remove(filepath)
class TestLinkObject(unittest.TestCase): # stack.add_link(x='q1', y=y, views=mean_views.subset('m1to6'), weights=weight) def setUp(self): self.path = './tests/' # self.path = '' project_name = 'Example Data (A)' # Load Example Data (A) data and meta into self name_data = '%s.csv' % (project_name) path_data = '%s%s' % (self.path, name_data) self.example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (self.path, name_meta) self.example_data_A_meta = load_json(path_meta) # The minimum list of variables required to populate a stack with all single*delimited set variations self.minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] self.setup_stack_Example_Data_A() def test_link_is_a_subclassed_dict(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum for x in xk: for y in yk: link = self.stack[dk][fk][x][y] self.assertIsInstance(link, dict) self.assertIsInstance(link, Link) def test_link_behaves_like_a_dict(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum key = "some_key_name" value = "some_value" for x in xk: for y in yk: link = self.stack[dk][fk][x][y] link[key] = value self.assertIn( key, link.keys(), msg="Link should have key {data_key}, but has {link_keys}".format( data_key=key, link_keys=link.keys() ) ) def test_get_meta(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum #test returned meta against stack meta for x in xk: for y in yk: link = self.stack[dk][fk][x][y] self.assertEqual(link.get_meta(), self.stack[dk].meta) def test_get_data(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum stack_data = self.stack[dk][fk].data #test returned data against stack data for x in xk: for y in yk: link_data = self.stack[dk][fk][x][y].get_data() self.assertTrue(link_data is stack_data) @classmethod def tearDownClass(self): self.stack = Stack("StackName") filepath ='./tests/'+self.stack.name+'.stack' if os.path.exists(filepath): os.remove(filepath) def is_empty(self, any_structure): if any_structure: #print('Structure is not empty.') return False else: #print('Structure is empty.') return True def create_key_stack(self, branch_pos="data"): """ Creates a dictionary that has the structure of the keys in the Stack It is used to loop through the stack without affecting it. """ key_stack = {} for data_key in self.stack: key_stack[data_key] = {} for the_filter in self.stack[data_key][branch_pos]: key_stack[data_key][the_filter] = {} for x in self.stack[data_key][branch_pos][the_filter]: key_stack[data_key][the_filter][x] = [] for y in self.stack[data_key][branch_pos][the_filter][x]: link = self.stack[data_key][branch_pos][the_filter][x][y] if not isinstance(link, Link): continue key_stack[data_key][the_filter][x].append(y) return key_stack def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = [ 'no_filter', 'Wave == 1' ] if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data( data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data ) for weight in weights: self.stack.add_link( data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight )
def get_stack(self, meta, data, xks, yks, views, weights): stack = Stack('test') stack.add_data('test', data, meta) stack.add_link(x=xks, y=yks, views=views, weights=weights) # Add two basic net net_views = ViewMapper( template={ 'method': QuantipyViews().frequency, 'kwargs': { 'iterators': { 'rel_to': [None, 'y'] } } }) net_views.add_method(name='Net 1-3', kwargs={ 'logic': [1, 2, 3], 'axis': 'x', 'text': { 'en-GB': '1-3' } }) net_views.add_method(name='Net 4-6', kwargs={ 'logic': [4, 5, 6], 'axis': 'x', 'text': { 'en-GB': '4-6' } }) stack.add_link(x=xks, y=yks, views=net_views, weights=weights) # Add block net net_views.add_method(name='Block net', kwargs={ 'logic': [{ 'bn1': [1, 2] }, { 'bn2': [2, 3] }, { 'bn3': [1, 3] }], 'axis': 'x' }) stack.add_link(x=xks, y=yks, views=net_views.subset(['Block net']), weights=weights) # Add NPS ## TO DO # Add standard deviation desc_views = ViewMapper( template={ 'method': QuantipyViews().descriptives, 'kwargs': { 'axis': 'x', 'iterators': { 'stats': ['mean', 'median', 'stddev'] } } }) desc_views.add_method(name='descriptives') stack.add_link(x=xks, y=yks, views=desc_views, weights=weights) # Add tests test_views = ViewMapper( template={ 'method': QuantipyViews().coltests, 'kwargs': { 'mimic': 'askia', 'iterators': { 'metric': ['props', 'means'], 'level': ['low', 'mid', 'high'] } } }) test_views.add_method('askia tests') stack.add_link(x=xks, y=yks, views=test_views, weights=weights) return stack
class TestChainObject(unittest.TestCase): def setUp(self): self.path = './tests/' # self.path = '' project_name = 'Example Data (A)' # Load Example Data (A) data and meta into self name_data = '%s.csv' % (project_name) path_data = '%s%s' % (self.path, name_data) self.example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (self.path, name_meta) self.example_data_A_meta = load_json(path_meta) # The minimum list of variables required to populate a stack with all single*delimited set variations self.minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] self.setup_stack_Example_Data_A() self.setup_chains_Example_Data_A() def test_save_chain(self): self.setup_chains_Example_Data_A() for chain in self.chains: chain.save(path=self.path) loaded_chain = Chain.load('%s%s.chain' % (self.path, chain.name)) # Create a dictionary with the attribute structure of the chain chain_attributes = test_helper.create_attribute_dict(chain) # Create a dictionary with the attribute structure of the chain loaded_chain_attributes = test_helper.create_attribute_dict(loaded_chain) # Ensure that we are not comparing the same variable (in memory) self.assertNotEqual(id(chain), id(loaded_chain)) # Make sure that this is working by altering the loaded_stack_attributes # and comparing the result. (It should fail) # Change a 'value' in the dict loaded_chain_attributes['__dict__']['name'] = 'SomeOtherName' with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value loaded_chain_attributes['__dict__']['name'] = chain_attributes['__dict__']['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Change a 'key' in the dict del loaded_chain_attributes['__dict__']['name'] loaded_chain_attributes['__dict__']['new_name'] = chain_attributes['__dict__']['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value del loaded_chain_attributes['__dict__']['new_name'] loaded_chain_attributes['__dict__']['name'] = chain_attributes['__dict__']['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Remove a key/value pair del loaded_chain_attributes['__dict__']['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # Cleanup if os.path.exists('./tests/{0}.chain'.format(chain.name)): os.remove('./tests/{0}.chain'.format(chain.name)) def test_validate_x_y_combination(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # check the correct error message is returned, irrespective of orientation... # error #1 expected_message = "If the number of keys for both x and y are greater than 1, whether or not you have specified the x and y values, orient_on must be either 'x' or 'y'." with self.assertRaises(ValueError) as error_message: _ = self.stack.get_chain( name='y', data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=views, post_process=True ) self.assertEqual(error_message.exception[0], expected_message) def test_lazy_name(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # get chain but do not name - y orientation chain_y = self.stack.get_chain( data_keys=self.stack.name, filters=fk, x=xk, y=yk[0], views=views, post_process=False ) # get chain but do not name - x orientation chain_x = self.stack.get_chain( data_keys=self.stack.name, filters=fk, x=xk[0], y=yk, views=views, post_process=False ) # check lazy_name is working as it should be self.assertEqual(chain_y.name, '[email protected]_1.cbase.counts.c%') self.assertEqual(chain_x.name, '[email protected]_1.cbase.counts.c%') def test_dervie_attributes(self): # check chain attributes self.assertEqual(self.chains[0].name, '@') self.assertEqual(self.chains[0].orientation, 'y') self.assertEqual(self.chains[0].source_name, '@') self.assertEqual(self.chains[0].len_of_axis, 5) self.assertEqual(self.chains[0].content_of_axis, ['q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[0].views, ['x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%']) self.assertEqual(self.chains[0].data_key, 'Example Data (A)') self.assertEqual(self.chains[0].filter, 'no_filter') self.assertEqual(self.chains[0].source_type, None) self.assertEqual(self.chains[-1].name, 'q5_1') self.assertEqual(self.chains[-1].orientation, 'x') self.assertEqual(self.chains[-1].source_name, 'q5_1') self.assertEqual(self.chains[-1].len_of_axis, 6) self.assertEqual(self.chains[-1].content_of_axis, ['@', 'q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[-1].views, ['x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%']) self.assertEqual(self.chains[-1].data_key, 'Example Data (A)') self.assertEqual(self.chains[-1].filter, 'no_filter') self.assertEqual(self.chains[-1].source_type, None) def test_post_process_shapes(self): # check chain attributes after post_processing self.assertEqual(self.chains[0].x_new_order, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[0].x_hidden_codes, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[0].y_new_order, None) self.assertEqual(self.chains[0].y_hidden_codes, None) self.assertEqual(self.chains[0].props_tests, []) self.assertEqual(self.chains[0].props_tests_levels, []) self.assertEqual(self.chains[0].has_props_tests, False) self.assertEqual(self.chains[0].means_tests, []) self.assertEqual(self.chains[0].means_tests_levels, []) self.assertEqual(self.chains[0].has_means_tests, False) self.assertEqual(self.chains[0].view_sizes, [[(1, 1), (3, 1), (3, 1)], [(1, 1), (5, 1), (5, 1)], [(1, 1), (8, 1), (8, 1)], [(1, 1), (9, 1), (9, 1)], [(1, 1), (7, 1), (7, 1)]]) self.assertEqual(self.chains[0].view_lengths, [[1, 3, 3], [1, 5, 5], [1, 8, 8], [1, 9, 9], [1, 7, 7]]) self.assertEqual(self.chains[0].source_length, 1) self.assertEqual(self.chains[-1].x_new_order, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[-1].x_hidden_codes, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[-1].y_new_order, None) self.assertEqual(self.chains[-1].y_hidden_codes, None) self.assertEqual(self.chains[-1].props_tests, []) self.assertEqual(self.chains[-1].props_tests_levels, []) self.assertEqual(self.chains[-1].has_props_tests, False) self.assertEqual(self.chains[-1].means_tests, []) self.assertEqual(self.chains[-1].means_tests_levels, []) self.assertEqual(self.chains[-1].has_means_tests, False) self.assertEqual(self.chains[-1].view_sizes, [[(1, 1), (7, 1), (7, 1)], [(1, 3), (7, 3), (7, 3)], [(1, 5), (7, 5), (7, 5)], [(1, 8), (7, 8), (7, 8)], [(1, 9), (7, 9), (7, 9)], [(1, 7), (7, 7), (7, 7)]]) self.assertEqual(self.chains[-1].view_lengths, [[1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7]]) self.assertEqual(self.chains[-1].source_length, 9) def test_describe(self): fk = 'no_filter' for chain in self.chains: chain_described = chain.describe() #test describe() returns a dataframe self.assertIsInstance(chain_described, pd.DataFrame) #test descibe() returns the expected dataframe - *no args* if chain.orientation == 'y': keys = chain[self.stack.name][fk].keys() views = chain[self.stack.name][fk][keys[0]][chain.source_name].keys() data = [self.stack.name]*(len(keys)*len(views)) filters = [fk]*(len(keys)*len(views)) x = [] for key in keys: x.extend([key]*len(views)) y = [chain.source_name]*(len(keys)*len(views)) view = [v for v in views]*len(keys) ones = [1]*(len(keys)*len(views)) df = pd.DataFrame({'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones}) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) elif chain.orientation == 'x': keys = chain[self.stack.name][fk][chain.source_name].keys() views = chain[self.stack.name][fk][chain.source_name][keys[0]].keys() data = [self.stack.name]*(len(keys)*len(views)) filters = [fk]*(len(keys)*len(views)) y = [] for key in keys: y.extend([key]*len(views)) x = [chain.source_name]*(len(keys)*len(views)) view = [v for v in views]*len(keys) ones = [1]*(len(keys)*len(views)) df = pd.DataFrame({'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones}) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) @classmethod def tearDownClass(self): self.stack = Stack("StackName") filepath ='./tests/'+self.stack.name+'.stack' if os.path.exists(filepath): os.remove(filepath) def is_empty(self, any_structure): if any_structure: #print('Structure is not empty.') return False else: #print('Structure is empty.') return True def create_key_stack(self, branch_pos="data"): """ Creates a dictionary that has the structure of the keys in the Stack It is used to loop through the stack without affecting it. """ key_stack = {} for data_key in self.stack: key_stack[data_key] = {} for the_filter in self.stack[data_key][branch_pos]: key_stack[data_key][the_filter] = {} for x in self.stack[data_key][branch_pos][the_filter]: key_stack[data_key][the_filter][x] = [] for y in self.stack[data_key][branch_pos][the_filter][x]: link = self.stack[data_key][branch_pos][the_filter][x][y] if not isinstance(link, Link): continue key_stack[data_key][the_filter][x].append(y) return key_stack def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'cbase', 'counts', 'c%'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data( data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data ) for weight in weights: self.stack.add_link( data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight ) def setup_chains_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, orient_on=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = [ 'x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%' ] self.chains = [] for y in yk: self.chains.append( self.stack.get_chain( name=y, data_keys=self.stack.name, filters='no_filter', x=xk, y=y, views=views, post_process=True ) ) for x in xk: self.chains.append( self.stack.get_chain( name=x, data_keys=self.stack.name, filters='no_filter', x=x, y=yk, views=views, post_process=True ) )
class TestChainObject(unittest.TestCase): def setUp(self): self.path = './tests/' # self.path = '' project_name = 'Example Data (A)' # Load Example Data (A) data and meta into self name_data = '%s.csv' % (project_name) path_data = '%s%s' % (self.path, name_data) self.example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (self.path, name_meta) self.example_data_A_meta = load_json(path_meta) # The minimum list of variables required to populate a stack with all single*delimited set variations self.minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] self.setup_stack_Example_Data_A() self.setup_chains_Example_Data_A() def test_save_chain(self): self.setup_chains_Example_Data_A() for chain in self.chains: chain.save(path=self.path) loaded_chain = Chain.load('%s%s.chain' % (self.path, chain.name)) # Create a dictionary with the attribute structure of the chain chain_attributes = test_helper.create_attribute_dict(chain) # Create a dictionary with the attribute structure of the chain loaded_chain_attributes = test_helper.create_attribute_dict( loaded_chain) # Ensure that we are not comparing the same variable (in memory) self.assertNotEqual(id(chain), id(loaded_chain)) # Make sure that this is working by altering the loaded_stack_attributes # and comparing the result. (It should fail) # Change a 'value' in the dict loaded_chain_attributes['__dict__']['name'] = 'SomeOtherName' with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value loaded_chain_attributes['__dict__']['name'] = chain_attributes[ '__dict__']['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Change a 'key' in the dict del loaded_chain_attributes['__dict__']['name'] loaded_chain_attributes['__dict__']['new_name'] = chain_attributes[ '__dict__']['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # reset the value del loaded_chain_attributes['__dict__']['new_name'] loaded_chain_attributes['__dict__']['name'] = chain_attributes[ '__dict__']['name'] self.assertEqual(chain_attributes, loaded_chain_attributes) # Remove a key/value pair del loaded_chain_attributes['__dict__']['name'] with self.assertRaises(AssertionError): self.assertEqual(chain_attributes, loaded_chain_attributes) # Cleanup if os.path.exists('./tests/{0}.chain'.format(chain.name)): os.remove('./tests/{0}.chain'.format(chain.name)) def test_validate_x_y_combination(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # check the correct error message is returned, irrespective of orientation... # error #1 expected_message = "If the number of keys for both x and y are greater than 1, whether or not you have specified the x and y values, orient_on must be either 'x' or 'y'." with self.assertRaises(ValueError) as error_message: _ = self.stack.get_chain(name='y', data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=views, post_process=True) self.assertEqual(error_message.exception[0], expected_message) def test_lazy_name(self): fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum views = ['cbase', 'counts', 'c%'] # get chain but do not name - y orientation chain_y = self.stack.get_chain(data_keys=self.stack.name, filters=fk, x=xk, y=yk[0], views=views, post_process=False) # get chain but do not name - x orientation chain_x = self.stack.get_chain(data_keys=self.stack.name, filters=fk, x=xk[0], y=yk, views=views, post_process=False) # check lazy_name is working as it should be self.assertEqual(chain_y.name, '[email protected]_1.cbase.counts.c%') self.assertEqual(chain_x.name, '[email protected]_1.cbase.counts.c%') def test_dervie_attributes(self): # check chain attributes self.assertEqual(self.chains[0].name, '@') self.assertEqual(self.chains[0].orientation, 'y') self.assertEqual(self.chains[0].source_name, '@') self.assertEqual(self.chains[0].len_of_axis, 5) self.assertEqual(self.chains[0].content_of_axis, ['q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[0].views, [ 'x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%' ]) self.assertEqual(self.chains[0].data_key, 'Example Data (A)') self.assertEqual(self.chains[0].filter, 'no_filter') self.assertEqual(self.chains[0].source_type, None) self.assertEqual(self.chains[-1].name, 'q5_1') self.assertEqual(self.chains[-1].orientation, 'x') self.assertEqual(self.chains[-1].source_name, 'q5_1') self.assertEqual(self.chains[-1].len_of_axis, 6) self.assertEqual(self.chains[-1].content_of_axis, ['@', 'q2b', 'Wave', 'q2', 'q3', 'q5_1']) self.assertEqual(self.chains[-1].views, [ 'x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%' ]) self.assertEqual(self.chains[-1].data_key, 'Example Data (A)') self.assertEqual(self.chains[-1].filter, 'no_filter') self.assertEqual(self.chains[-1].source_type, None) def test_post_process_shapes(self): # check chain attributes after post_processing self.assertEqual( self.chains[0].x_new_order, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual( self.chains[0].x_hidden_codes, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[0].y_new_order, None) self.assertEqual(self.chains[0].y_hidden_codes, None) self.assertEqual(self.chains[0].props_tests, []) self.assertEqual(self.chains[0].props_tests_levels, []) self.assertEqual(self.chains[0].has_props_tests, False) self.assertEqual(self.chains[0].means_tests, []) self.assertEqual(self.chains[0].means_tests_levels, []) self.assertEqual(self.chains[0].has_means_tests, False) self.assertEqual( self.chains[0].view_sizes, [[(1, 1), (3, 1), (3, 1)], [(1, 1), (5, 1), (5, 1)], [(1, 1), (8, 1), (8, 1)], [(1, 1), (9, 1), (9, 1)], [(1, 1), (7, 1), (7, 1)]]) self.assertEqual( self.chains[0].view_lengths, [[1, 3, 3], [1, 5, 5], [1, 8, 8], [1, 9, 9], [1, 7, 7]]) self.assertEqual(self.chains[0].source_length, 1) self.assertEqual(self.chains[-1].x_new_order, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[-1].x_hidden_codes, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]) self.assertEqual(self.chains[-1].y_new_order, None) self.assertEqual(self.chains[-1].y_hidden_codes, None) self.assertEqual(self.chains[-1].props_tests, []) self.assertEqual(self.chains[-1].props_tests_levels, []) self.assertEqual(self.chains[-1].has_props_tests, False) self.assertEqual(self.chains[-1].means_tests, []) self.assertEqual(self.chains[-1].means_tests_levels, []) self.assertEqual(self.chains[-1].has_means_tests, False) self.assertEqual(self.chains[-1].view_sizes, [[(1, 1), (7, 1), (7, 1)], [(1, 3), (7, 3), (7, 3)], [(1, 5), (7, 5), (7, 5)], [(1, 8), (7, 8), (7, 8)], [(1, 9), (7, 9), (7, 9)], [(1, 7), (7, 7), (7, 7)]]) self.assertEqual( self.chains[-1].view_lengths, [[1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7], [1, 7, 7]]) self.assertEqual(self.chains[-1].source_length, 9) def test_describe(self): fk = 'no_filter' for chain in self.chains: chain_described = chain.describe() #test describe() returns a dataframe self.assertIsInstance(chain_described, pd.DataFrame) #test descibe() returns the expected dataframe - *no args* if chain.orientation == 'y': keys = chain[self.stack.name][fk].keys() views = chain[self.stack.name][fk][keys[0]][ chain.source_name].keys() data = [self.stack.name] * (len(keys) * len(views)) filters = [fk] * (len(keys) * len(views)) x = [] for key in keys: x.extend([key] * len(views)) y = [chain.source_name] * (len(keys) * len(views)) view = [v for v in views] * len(keys) ones = [1] * (len(keys) * len(views)) df = pd.DataFrame({ 'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones }) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) elif chain.orientation == 'x': keys = chain[self.stack.name][fk][chain.source_name].keys() views = chain[self.stack.name][fk][chain.source_name][ keys[0]].keys() data = [self.stack.name] * (len(keys) * len(views)) filters = [fk] * (len(keys) * len(views)) y = [] for key in keys: y.extend([key] * len(views)) x = [chain.source_name] * (len(keys) * len(views)) view = [v for v in views] * len(keys) ones = [1] * (len(keys) * len(views)) df = pd.DataFrame({ 'data': data, 'filter': filters, 'x': x, 'y': y, 'view': view, '#': ones }) df = df[chain_described.columns.tolist()] assert_frame_equal(chain_described, df) @classmethod def tearDownClass(self): self.stack = Stack("StackName") filepath = './tests/' + self.stack.name + '.stack' if os.path.exists(filepath): os.remove(filepath) def is_empty(self, any_structure): if any_structure: #print('Structure is not empty.') return False else: #print('Structure is empty.') return True def create_key_stack(self, branch_pos="data"): """ Creates a dictionary that has the structure of the keys in the Stack It is used to loop through the stack without affecting it. """ key_stack = {} for data_key in self.stack: key_stack[data_key] = {} for the_filter in self.stack[data_key][branch_pos]: key_stack[data_key][the_filter] = {} for x in self.stack[data_key][branch_pos][the_filter]: key_stack[data_key][the_filter][x] = [] for y in self.stack[data_key][branch_pos][the_filter][x]: link = self.stack[data_key][branch_pos][the_filter][x][ y] if not isinstance(link, Link): continue key_stack[data_key][the_filter][x].append(y) return key_stack def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default', 'cbase', 'counts', 'c%'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data(data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data) for weight in weights: self.stack.add_link(data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight) def setup_chains_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, orient_on=None): if fk is None: fk = 'no_filter' if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = [ 'x|frequency|x:y|||cbase', 'x|frequency||||counts', 'x|frequency||y||c%' ] self.chains = [] for y in yk: self.chains.append( self.stack.get_chain(name=y, data_keys=self.stack.name, filters='no_filter', x=xk, y=y, views=views, post_process=True)) for x in xk: self.chains.append( self.stack.get_chain(name=x, data_keys=self.stack.name, filters='no_filter', x=x, y=yk, views=views, post_process=True))
def test_iterations_object(self): # Set up path to example files path_tests = self.path project_name = 'Example Data (A)' # Load Example Data (A) data and meta name_data = '%s.csv' % (project_name) path_data = '%s%s' % (path_tests, name_data) example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (path_tests, name_meta) example_data_A_meta = load_json(path_meta) # Variables by type for Example Data A eda_int = ['record_number', 'unique_id', 'age', 'birth_day', 'birth_month'] eda_float = ['weight', 'weight_a', 'weight_b'] eda_single = ['gender', 'locality', 'ethnicity', 'religion', 'q1'] eda_delimited_set = ['q2', 'q3', 'q8', 'q9'] eda_string = ['q8a', 'q9a'] eda_date = ['start_time', 'end_time'] eda_time = ['duration'] eda_array = ['q5', 'q6', 'q7'] eda_minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] # Create basic stack stack = Stack(name=project_name) stack.add_data(project_name, example_data_A_data, example_data_A_meta) stack.add_link( data_keys=project_name, filters=['no_filter'], x=eda_minimum, y=['@'], views=QuantipyViews(['default', 'cbase', 'counts', 'c%']), weights=[None, 'weight_a', 'weight_b'] ) # Get list of views created views_present = stack.describe(index=['view']) # Test that weighted an unweighted versions of all basic views # were created self.assertIn('x|default|x:y|||default', views_present) self.assertIn('x|default|x:y||weight_a|default', views_present) self.assertIn('x|default|x:y||weight_b|default', views_present) self.assertIn('x|frequency|x:y|||cbase', views_present) self.assertIn('x|frequency|x:y||weight_a|cbase', views_present) self.assertIn('x|frequency|x:y||weight_b|cbase', views_present) self.assertIn('x|frequency||y||c%', views_present) self.assertIn('x|frequency||y|weight_a|c%', views_present) self.assertIn('x|frequency||y|weight_b|c%', views_present) self.assertIn('x|frequency||||counts', views_present) self.assertIn('x|frequency|||weight_a|counts', views_present) self.assertIn('x|frequency|||weight_b|counts', views_present) # Create a ViewMapper using the iterator object in a template xnets = ViewMapper( template={ 'method': QuantipyViews().frequency, 'kwargs': { 'axis': 'x', 'groups': ['Nets'], 'iterators': { 'rel_to': [None, 'y'], 'weights': [None, 'weight_a'] } } }) # Add a method to the xnets ViewMapper, then use it to generate additional # views which include N/c% and unweighted/weighted xnets.add_method(name='ever', kwargs={'text': 'Ever', 'logic': [1, 2]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever', views_present) # Add another method to the xnets ViewMapper, but then override the weights # in the iterator object using the stack.add_link(weights) parameter stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever']), weights='weight_b') # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created xnets.add_method(name='ever (multi test)', kwargs={'text': 'Ever', 'logic': [1, 2]}) xnets.add_method(name='never (multi test)', kwargs={'text': 'Never', 'logic': [2, 3]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever (multi test)', 'never (multi test)'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_a|never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_a|never (multi test)', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created, in this case that the weights arg for stack.add_link() overrides # what the iterator object is asking for xnets.add_method(name='ever (weights test)', kwargs={'text': 'Ever', 'logic': [1, 2]}) xnets.add_method(name='never (weights test)', kwargs={'text': 'Never', 'logic': [2, 3]}) stack.add_link( x='q2b', y=['@'], views=xnets.subset(['ever (weights test)', 'never (weights test)']), weights=['weight_b'] ) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertNotIn('x|frequency|x[(1,2)]:y|||ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(1,2)]:y|y||ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|||never (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|y||never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_b|never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_b|never (weights test)', views_present)
class TestViewObject(unittest.TestCase): def setUp(self): self.path = './tests/' # self.path = '' self.filepath = '%sengine_B_data.csv' % (self.path) self.metapath = '%sengine_B_meta.json' % (self.path) self.stack = Stack("StackName") self.stack.seperator = ',' self.stack.decoding = "UTF-8" self.data = pd.DataFrame.from_csv(self.filepath) self.meta = load_json(self.metapath) self.stack.add_data(data_key="Jan", meta=self.meta, data=self.data) # self.x_names=['age', 'cost_breakfast', 'age_group', 'endtime', 'name', 'q4'], self.x_names = ['age', 'cost_breakfast', 'age_group', 'q4'] # self._types = ['int', 'float', 'single', 'date', 'string', 'delimited set'] self.x_types = ['int', 'float', 'single', 'delimited set'] self.y_names = ['profile_gender'] def test_add_method(self): views = ViewMapper() #At first there should not be method 'plus' in views self.assertRaises(KeyError, lambda: views['plus']) self.assertNotIn('plus', views.keys()) #Plus method added: views.add_method('plus', lambda x: 2) #Checked for the existance of the plus method self.assertIsNotNone(views['plus']['method']) self.assertIsNotNone(views['plus']['kwargs']) self.assertIn('plus', views.keys()) #Check to see wether a method is overridden properly views.add_method('plus', 'me') #The method should have changed from lambda x:2 to me self.assertEqual(views['plus']['method'], 'me') # Check to see wether a method is overridden properly views.add_method('minus', 'x', {'key': 'value'}) self.assertEqual(views['minus']['method'], 'x') def test__custom_methods(self): views = ViewMapper() views.add_method('minus_x', 'x', {'key': 'value'}) views.add_method('minus_y', 'y') views.add_method('minus_z', 'z') for view in ['minus_x', 'minus_y', 'minus_z']: self.assertIn(view, views._custom_methods()) for view in ['X', 'Y', 'Z']: self.assertNotIn(view, views._custom_methods()) def test__get_method_types(self): #not checked - time & string - need to implemented #examples: time - "endtime" # string - "name" views = QuantipyViews(['default']) self.stack.add_link(data_keys="Jan", x=self.x_names, y=self.y_names, views=views) for x_type, x_name in zip(self.x_types, self.x_names): link = self.stack['Jan']['no_filter'][x_name]['profile_gender'] self.assertEqual(x_type, views._get_method_types(link)[0]) def test__apply_to(self): #not checked - time & string - need to implemented #examples: time - "endtime" # string - "name" views = QuantipyViews(['cbase', 'counts', 'mean']) # This matches the view method names to their resulting view key # based on the new view notation notation = { 'default': 'x|default|x:y|||default', 'cbase': 'x|frequency|x:y|||cbase', 'counts': 'x|frequency||||counts', 'mean': 'x|mean|x:y|||mean' } x_names = ['profile_gender', 'age_group', 'q4'] y_names = x_names self.stack.add_link(data_keys="Jan", x=x_names, y=y_names) for a_x in self.stack['Jan']['no_filter'].keys(): for a_y in self.stack['Jan']['no_filter'][a_x].keys(): link = self.stack['Jan']['no_filter'][a_x][a_y] if not link.y == "@": views._apply_to(link) for view in views.keys(): for a_x in self.stack['Jan']['no_filter'].keys(): for a_y in self.stack['Jan']['no_filter'][a_x].keys(): if views[view]['method'] == 'descriptives': if a_x == 'q4': self.assertNotIn(notation[view], self.stack['Jan']['no_filter'][a_x][a_y].keys()) else: self.assertIn(notation[view], self.stack['Jan']['no_filter'][a_x][a_y].keys()) else: self.assertIn(notation[view], self.stack['Jan']['no_filter'][a_x][a_y].keys()) def test_get_view_iterations(self): views = QuantipyViews(['default']) iterators = {'A': [1, 2], 'B': [3, 4, 5], 'C': [6, 7, 8, 9]} iterations = views.__get_view_iterations__(iterators) # Test that iterations has the anticipated number of items # It should be the multiplication of the len of all of # iterators lists, in this case 2x3x4=24 self.assertEqual(len(iterations), 24) self.assertEqual(iterations[0], {'A': 1, 'B': 3, 'C': 6}) self.assertEqual(iterations[1], {'A': 1, 'B': 4, 'C': 6}) self.assertEqual(iterations[2], {'A': 1, 'B': 5, 'C': 6}) self.assertEqual(iterations[3], {'A': 1, 'B': 3, 'C': 7}) self.assertEqual(iterations[4], {'A': 1, 'B': 4, 'C': 7}) self.assertEqual(iterations[5], {'A': 1, 'B': 5, 'C': 7}) self.assertEqual(iterations[6], {'A': 1, 'B': 3, 'C': 8}) self.assertEqual(iterations[7], {'A': 1, 'B': 4, 'C': 8}) self.assertEqual(iterations[8], {'A': 1, 'B': 5, 'C': 8}) self.assertEqual(iterations[9], {'A': 1, 'B': 3, 'C': 9}) self.assertEqual(iterations[10], {'A': 1, 'B': 4, 'C': 9}) self.assertEqual(iterations[11], {'A': 1, 'B': 5, 'C': 9}) self.assertEqual(iterations[12], {'A': 2, 'B': 3, 'C': 6}) self.assertEqual(iterations[13], {'A': 2, 'B': 4, 'C': 6}) self.assertEqual(iterations[14], {'A': 2, 'B': 5, 'C': 6}) self.assertEqual(iterations[15], {'A': 2, 'B': 3, 'C': 7}) self.assertEqual(iterations[16], {'A': 2, 'B': 4, 'C': 7}) self.assertEqual(iterations[17], {'A': 2, 'B': 5, 'C': 7}) self.assertEqual(iterations[18], {'A': 2, 'B': 3, 'C': 8}) self.assertEqual(iterations[19], {'A': 2, 'B': 4, 'C': 8}) self.assertEqual(iterations[20], {'A': 2, 'B': 5, 'C': 8}) self.assertEqual(iterations[21], {'A': 2, 'B': 3, 'C': 9}) self.assertEqual(iterations[22], {'A': 2, 'B': 4, 'C': 9}) self.assertEqual(iterations[23], {'A': 2, 'B': 5, 'C': 9}) def test_iterations_object(self): # Set up path to example files path_tests = self.path project_name = 'Example Data (A)' # Load Example Data (A) data and meta name_data = '%s.csv' % (project_name) path_data = '%s%s' % (path_tests, name_data) example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (path_tests, name_meta) example_data_A_meta = load_json(path_meta) # Variables by type for Example Data A eda_int = ['record_number', 'unique_id', 'age', 'birth_day', 'birth_month'] eda_float = ['weight', 'weight_a', 'weight_b'] eda_single = ['gender', 'locality', 'ethnicity', 'religion', 'q1'] eda_delimited_set = ['q2', 'q3', 'q8', 'q9'] eda_string = ['q8a', 'q9a'] eda_date = ['start_time', 'end_time'] eda_time = ['duration'] eda_array = ['q5', 'q6', 'q7'] eda_minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] # Create basic stack stack = Stack(name=project_name) stack.add_data(project_name, example_data_A_data, example_data_A_meta) stack.add_link( data_keys=project_name, filters=['no_filter'], x=eda_minimum, y=['@'], views=QuantipyViews(['default', 'cbase', 'counts', 'c%']), weights=[None, 'weight_a', 'weight_b'] ) # Get list of views created views_present = stack.describe(index=['view']) # Test that weighted an unweighted versions of all basic views # were created self.assertIn('x|default|x:y|||default', views_present) self.assertIn('x|default|x:y||weight_a|default', views_present) self.assertIn('x|default|x:y||weight_b|default', views_present) self.assertIn('x|frequency|x:y|||cbase', views_present) self.assertIn('x|frequency|x:y||weight_a|cbase', views_present) self.assertIn('x|frequency|x:y||weight_b|cbase', views_present) self.assertIn('x|frequency||y||c%', views_present) self.assertIn('x|frequency||y|weight_a|c%', views_present) self.assertIn('x|frequency||y|weight_b|c%', views_present) self.assertIn('x|frequency||||counts', views_present) self.assertIn('x|frequency|||weight_a|counts', views_present) self.assertIn('x|frequency|||weight_b|counts', views_present) # Create a ViewMapper using the iterator object in a template xnets = ViewMapper( template={ 'method': QuantipyViews().frequency, 'kwargs': { 'axis': 'x', 'groups': ['Nets'], 'iterators': { 'rel_to': [None, 'y'], 'weights': [None, 'weight_a'] } } }) # Add a method to the xnets ViewMapper, then use it to generate additional # views which include N/c% and unweighted/weighted xnets.add_method(name='ever', kwargs={'text': 'Ever', 'logic': [1, 2]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever', views_present) # Add another method to the xnets ViewMapper, but then override the weights # in the iterator object using the stack.add_link(weights) parameter stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever']), weights='weight_b') # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created xnets.add_method(name='ever (multi test)', kwargs={'text': 'Ever', 'logic': [1, 2]}) xnets.add_method(name='never (multi test)', kwargs={'text': 'Never', 'logic': [2, 3]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever (multi test)', 'never (multi test)'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_a|never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_a|never (multi test)', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created, in this case that the weights arg for stack.add_link() overrides # what the iterator object is asking for xnets.add_method(name='ever (weights test)', kwargs={'text': 'Ever', 'logic': [1, 2]}) xnets.add_method(name='never (weights test)', kwargs={'text': 'Never', 'logic': [2, 3]}) stack.add_link( x='q2b', y=['@'], views=xnets.subset(['ever (weights test)', 'never (weights test)']), weights=['weight_b'] ) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertNotIn('x|frequency|x[(1,2)]:y|||ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(1,2)]:y|y||ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|||never (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|y||never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_b|never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_b|never (weights test)', views_present)
def test_iterations_object(self): # Set up path to example files path_tests = self.path project_name = 'Example Data (A)' # Load Example Data (A) data and meta name_data = '%s.csv' % (project_name) path_data = '%s%s' % (path_tests, name_data) example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (path_tests, name_meta) example_data_A_meta = load_json(path_meta) # Variables by type for Example Data A eda_int = [ 'record_number', 'unique_id', 'age', 'birth_day', 'birth_month' ] eda_float = ['weight', 'weight_a', 'weight_b'] eda_single = ['gender', 'locality', 'ethnicity', 'religion', 'q1'] eda_delimited_set = ['q2', 'q3', 'q8', 'q9'] eda_string = ['q8a', 'q9a'] eda_date = ['start_time', 'end_time'] eda_time = ['duration'] eda_array = ['q5', 'q6', 'q7'] eda_minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] # Create basic stack stack = Stack(name=project_name) stack.add_data(project_name, example_data_A_data, example_data_A_meta) stack.add_link(data_keys=project_name, filters=['no_filter'], x=eda_minimum, y=['@'], views=QuantipyViews( ['default', 'cbase', 'counts', 'c%']), weights=[None, 'weight_a', 'weight_b']) # Get list of views created views_present = stack.describe(index=['view']) # Test that weighted an unweighted versions of all basic views # were created self.assertIn('x|default|x:y|||default', views_present) self.assertIn('x|default|x:y||weight_a|default', views_present) self.assertIn('x|default|x:y||weight_b|default', views_present) self.assertIn('x|frequency|x:y|||cbase', views_present) self.assertIn('x|frequency|x:y||weight_a|cbase', views_present) self.assertIn('x|frequency|x:y||weight_b|cbase', views_present) self.assertIn('x|frequency||y||c%', views_present) self.assertIn('x|frequency||y|weight_a|c%', views_present) self.assertIn('x|frequency||y|weight_b|c%', views_present) self.assertIn('x|frequency||||counts', views_present) self.assertIn('x|frequency|||weight_a|counts', views_present) self.assertIn('x|frequency|||weight_b|counts', views_present) # Create a ViewMapper using the iterator object in a template xnets = ViewMapper( template={ 'method': QuantipyViews().frequency, 'kwargs': { 'axis': 'x', 'groups': ['Nets'], 'iterators': { 'rel_to': [None, 'y'], 'weights': [None, 'weight_a'] } } }) # Add a method to the xnets ViewMapper, then use it to generate additional # views which include N/c% and unweighted/weighted xnets.add_method(name='ever', kwargs={'text': 'Ever', 'logic': [1, 2]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever', views_present) # Add another method to the xnets ViewMapper, but then override the weights # in the iterator object using the stack.add_link(weights) parameter stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever']), weights='weight_b') # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created xnets.add_method(name='ever (multi test)', kwargs={ 'text': 'Ever', 'logic': [1, 2] }) xnets.add_method(name='never (multi test)', kwargs={ 'text': 'Never', 'logic': [2, 3] }) stack.add_link(x='q2b', y=['@'], views=xnets.subset( ['ever (multi test)', 'never (multi test)'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_a|never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_a|never (multi test)', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created, in this case that the weights arg for stack.add_link() overrides # what the iterator object is asking for xnets.add_method(name='ever (weights test)', kwargs={ 'text': 'Ever', 'logic': [1, 2] }) xnets.add_method(name='never (weights test)', kwargs={ 'text': 'Never', 'logic': [2, 3] }) stack.add_link(x='q2b', y=['@'], views=xnets.subset( ['ever (weights test)', 'never (weights test)']), weights=['weight_b']) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertNotIn('x|frequency|x[(1,2)]:y|||ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(1,2)]:y|y||ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|||never (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|y||never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_b|never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_b|never (weights test)', views_present)
def tearDownClass(self): self.stack = Stack("StackName") filepath = './tests/' + self.stack.name + '.stack' if os.path.exists(filepath): os.remove(filepath)
class TestLinkObject(unittest.TestCase): # stack.add_link(x='q1', y=y, views=mean_views.subset('m1to6'), weights=weight) def setUp(self): self.path = './tests/' # self.path = '' project_name = 'Example Data (A)' # Load Example Data (A) data and meta into self name_data = '%s.csv' % (project_name) path_data = '%s%s' % (self.path, name_data) self.example_data_A_data = pd.read_csv(path_data) self.example_data_A_data = dataframe_fix_string_types( self.example_data_A_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (self.path, name_meta) self.example_data_A_meta = load_json(path_meta) # The minimum list of variables required to populate a stack with all single*delimited set variations self.minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] self.setup_stack_Example_Data_A() def test_link_is_a_subclassed_dict(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum for x in xk: for y in yk: link = self.stack[dk][fk][x][y] self.assertIsInstance(link, dict) self.assertIsInstance(link, Link) def test_link_behaves_like_a_dict(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum key = "some_key_name" value = "some_value" for x in xk: for y in yk: link = self.stack[dk][fk][x][y] link[key] = value self.assertIn( key, link.keys(), msg="Link should have key {data_key}, but has {link_keys}". format(data_key=key, link_keys=link.keys())) def test_get_meta(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum #test returned meta against stack meta for x in xk: for y in yk: link = self.stack[dk][fk][x][y] self.assertEqual(link.get_meta(), self.stack[dk].meta) def test_get_data(self): dk = self.stack.name fk = 'no_filter' xk = self.minimum yk = ['@'] + self.minimum stack_data = self.stack[dk][fk].data #test returned data against stack data for x in xk: for y in yk: link_data = self.stack[dk][fk][x][y].get_data() self.assertTrue(link_data is stack_data) @classmethod def tearDownClass(self): self.stack = Stack("StackName") filepath = './tests/' + self.stack.name + '.stack' if os.path.exists(filepath): os.remove(filepath) def is_empty(self, any_structure): if any_structure: #print('Structure is not empty.') return False else: #print('Structure is empty.') return True def create_key_stack(self, branch_pos="data"): """ Creates a dictionary that has the structure of the keys in the Stack It is used to loop through the stack without affecting it. """ key_stack = {} for data_key in self.stack: key_stack[data_key] = {} for the_filter in self.stack[data_key][branch_pos]: key_stack[data_key][the_filter] = {} for x in self.stack[data_key][branch_pos][the_filter]: key_stack[data_key][the_filter][x] = [] for y in self.stack[data_key][branch_pos][the_filter][x]: link = self.stack[data_key][branch_pos][the_filter][x][ y] if not isinstance(link, Link): continue key_stack[data_key][the_filter][x].append(y) return key_stack def setup_stack_Example_Data_A(self, fk=None, xk=None, yk=None, views=None, weights=None): if fk is None: fk = ['no_filter', 'Wave == 1'] if xk is None: xk = self.minimum if yk is None: yk = ['@'] + self.minimum if views is None: views = ['default'] if not isinstance(weights, list): weights = [weights] self.stack = Stack(name="Example Data (A)") self.stack.add_data(data_key=self.stack.name, meta=self.example_data_A_meta, data=self.example_data_A_data) for weight in weights: self.stack.add_link(data_keys=self.stack.name, filters=fk, x=xk, y=yk, views=QuantipyViews(views), weights=weight)
class TestViewObject(unittest.TestCase): def setUp(self): self.path = './tests/' # self.path = '' self.filepath = '%sengine_B_data.csv' % (self.path) self.metapath = '%sengine_B_meta.json' % (self.path) self.stack = Stack("StackName") self.stack.seperator = ',' self.stack.decoding = "UTF-8" self.data = pd.DataFrame.from_csv(self.filepath) self.meta = load_json(self.metapath) self.stack.add_data(data_key="Jan", meta=self.meta, data=self.data) # self.x_names=['age', 'cost_breakfast', 'age_group', 'endtime', 'name', 'q4'], self.x_names = ['age', 'cost_breakfast', 'age_group', 'q4'] # self._types = ['int', 'float', 'single', 'date', 'string', 'delimited set'] self.x_types = ['int', 'float', 'single', 'delimited set'] self.y_names = ['profile_gender'] def test_add_method(self): views = ViewMapper() #At first there should not be method 'plus' in views self.assertRaises(KeyError, lambda: views['plus']) self.assertNotIn('plus', views.keys()) #Plus method added: views.add_method('plus', lambda x: 2) #Checked for the existance of the plus method self.assertIsNotNone(views['plus']['method']) self.assertIsNotNone(views['plus']['kwargs']) self.assertIn('plus', views.keys()) #Check to see wether a method is overridden properly views.add_method('plus', 'me') #The method should have changed from lambda x:2 to me self.assertEqual(views['plus']['method'], 'me') # Check to see wether a method is overridden properly views.add_method('minus', 'x', {'key': 'value'}) self.assertEqual(views['minus']['method'], 'x') def test__custom_methods(self): views = ViewMapper() views.add_method('minus_x', 'x', {'key': 'value'}) views.add_method('minus_y', 'y') views.add_method('minus_z', 'z') for view in ['minus_x', 'minus_y', 'minus_z']: self.assertIn(view, views._custom_methods()) for view in ['X', 'Y', 'Z']: self.assertNotIn(view, views._custom_methods()) def test__get_method_types(self): #not checked - time & string - need to implemented #examples: time - "endtime" # string - "name" views = QuantipyViews(['default']) self.stack.add_link(data_keys="Jan", x=self.x_names, y=self.y_names, views=views) for x_type, x_name in zip(self.x_types, self.x_names): link = self.stack['Jan']['no_filter'][x_name]['profile_gender'] self.assertEqual(x_type, views._get_method_types(link)[0]) def test__apply_to(self): #not checked - time & string - need to implemented #examples: time - "endtime" # string - "name" views = QuantipyViews(['cbase', 'counts', 'mean']) # This matches the view method names to their resulting view key # based on the new view notation notation = { 'default': 'x|default|x:y|||default', 'cbase': 'x|frequency|x:y|||cbase', 'counts': 'x|frequency||||counts', 'mean': 'x|mean|x:y|||mean' } x_names = ['profile_gender', 'age_group', 'q4'] y_names = x_names self.stack.add_link(data_keys="Jan", x=x_names, y=y_names) for a_x in self.stack['Jan']['no_filter'].keys(): for a_y in self.stack['Jan']['no_filter'][a_x].keys(): link = self.stack['Jan']['no_filter'][a_x][a_y] if not link.y == "@": views._apply_to(link) for view in views.keys(): for a_x in self.stack['Jan']['no_filter'].keys(): for a_y in self.stack['Jan']['no_filter'][a_x].keys(): if views[view]['method'] == 'descriptives': if a_x == 'q4': self.assertNotIn( notation[view], self.stack['Jan']['no_filter'] [a_x][a_y].keys()) else: self.assertIn( notation[view], self.stack['Jan']['no_filter'] [a_x][a_y].keys()) else: self.assertIn( notation[view], self.stack['Jan']['no_filter'][a_x][a_y].keys()) def test_get_view_iterations(self): views = QuantipyViews(['default']) iterators = {'A': [1, 2], 'B': [3, 4, 5], 'C': [6, 7, 8, 9]} iterations = views.__get_view_iterations__(iterators) # Test that iterations has the anticipated number of items # It should be the multiplication of the len of all of # iterators lists, in this case 2x3x4=24 self.assertEqual(len(iterations), 24) self.assertEqual(iterations[0], {'A': 1, 'B': 3, 'C': 6}) self.assertEqual(iterations[1], {'A': 1, 'B': 4, 'C': 6}) self.assertEqual(iterations[2], {'A': 1, 'B': 5, 'C': 6}) self.assertEqual(iterations[3], {'A': 1, 'B': 3, 'C': 7}) self.assertEqual(iterations[4], {'A': 1, 'B': 4, 'C': 7}) self.assertEqual(iterations[5], {'A': 1, 'B': 5, 'C': 7}) self.assertEqual(iterations[6], {'A': 1, 'B': 3, 'C': 8}) self.assertEqual(iterations[7], {'A': 1, 'B': 4, 'C': 8}) self.assertEqual(iterations[8], {'A': 1, 'B': 5, 'C': 8}) self.assertEqual(iterations[9], {'A': 1, 'B': 3, 'C': 9}) self.assertEqual(iterations[10], {'A': 1, 'B': 4, 'C': 9}) self.assertEqual(iterations[11], {'A': 1, 'B': 5, 'C': 9}) self.assertEqual(iterations[12], {'A': 2, 'B': 3, 'C': 6}) self.assertEqual(iterations[13], {'A': 2, 'B': 4, 'C': 6}) self.assertEqual(iterations[14], {'A': 2, 'B': 5, 'C': 6}) self.assertEqual(iterations[15], {'A': 2, 'B': 3, 'C': 7}) self.assertEqual(iterations[16], {'A': 2, 'B': 4, 'C': 7}) self.assertEqual(iterations[17], {'A': 2, 'B': 5, 'C': 7}) self.assertEqual(iterations[18], {'A': 2, 'B': 3, 'C': 8}) self.assertEqual(iterations[19], {'A': 2, 'B': 4, 'C': 8}) self.assertEqual(iterations[20], {'A': 2, 'B': 5, 'C': 8}) self.assertEqual(iterations[21], {'A': 2, 'B': 3, 'C': 9}) self.assertEqual(iterations[22], {'A': 2, 'B': 4, 'C': 9}) self.assertEqual(iterations[23], {'A': 2, 'B': 5, 'C': 9}) def test_iterations_object(self): # Set up path to example files path_tests = self.path project_name = 'Example Data (A)' # Load Example Data (A) data and meta name_data = '%s.csv' % (project_name) path_data = '%s%s' % (path_tests, name_data) example_data_A_data = pd.DataFrame.from_csv(path_data) name_meta = '%s.json' % (project_name) path_meta = '%s%s' % (path_tests, name_meta) example_data_A_meta = load_json(path_meta) # Variables by type for Example Data A eda_int = [ 'record_number', 'unique_id', 'age', 'birth_day', 'birth_month' ] eda_float = ['weight', 'weight_a', 'weight_b'] eda_single = ['gender', 'locality', 'ethnicity', 'religion', 'q1'] eda_delimited_set = ['q2', 'q3', 'q8', 'q9'] eda_string = ['q8a', 'q9a'] eda_date = ['start_time', 'end_time'] eda_time = ['duration'] eda_array = ['q5', 'q6', 'q7'] eda_minimum = ['q2b', 'Wave', 'q2', 'q3', 'q5_1'] # Create basic stack stack = Stack(name=project_name) stack.add_data(project_name, example_data_A_data, example_data_A_meta) stack.add_link(data_keys=project_name, filters=['no_filter'], x=eda_minimum, y=['@'], views=QuantipyViews( ['default', 'cbase', 'counts', 'c%']), weights=[None, 'weight_a', 'weight_b']) # Get list of views created views_present = stack.describe(index=['view']) # Test that weighted an unweighted versions of all basic views # were created self.assertIn('x|default|x:y|||default', views_present) self.assertIn('x|default|x:y||weight_a|default', views_present) self.assertIn('x|default|x:y||weight_b|default', views_present) self.assertIn('x|frequency|x:y|||cbase', views_present) self.assertIn('x|frequency|x:y||weight_a|cbase', views_present) self.assertIn('x|frequency|x:y||weight_b|cbase', views_present) self.assertIn('x|frequency||y||c%', views_present) self.assertIn('x|frequency||y|weight_a|c%', views_present) self.assertIn('x|frequency||y|weight_b|c%', views_present) self.assertIn('x|frequency||||counts', views_present) self.assertIn('x|frequency|||weight_a|counts', views_present) self.assertIn('x|frequency|||weight_b|counts', views_present) # Create a ViewMapper using the iterator object in a template xnets = ViewMapper( template={ 'method': QuantipyViews().frequency, 'kwargs': { 'axis': 'x', 'groups': ['Nets'], 'iterators': { 'rel_to': [None, 'y'], 'weights': [None, 'weight_a'] } } }) # Add a method to the xnets ViewMapper, then use it to generate additional # views which include N/c% and unweighted/weighted xnets.add_method(name='ever', kwargs={'text': 'Ever', 'logic': [1, 2]}) stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever', views_present) # Add another method to the xnets ViewMapper, but then override the weights # in the iterator object using the stack.add_link(weights) parameter stack.add_link(x='q2b', y=['@'], views=xnets.subset(['ever']), weights='weight_b') # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created xnets.add_method(name='ever (multi test)', kwargs={ 'text': 'Ever', 'logic': [1, 2] }) xnets.add_method(name='never (multi test)', kwargs={ 'text': 'Never', 'logic': [2, 3] }) stack.add_link(x='q2b', y=['@'], views=xnets.subset( ['ever (multi test)', 'never (multi test)'])) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertIn('x|frequency|x[(1,2)]:y|||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y||ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_a|ever (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y||never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_a|never (multi test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_a|never (multi test)', views_present) # Add two methods and apply them at the same time, make sure all expected iterations # of both were created, in this case that the weights arg for stack.add_link() overrides # what the iterator object is asking for xnets.add_method(name='ever (weights test)', kwargs={ 'text': 'Ever', 'logic': [1, 2] }) xnets.add_method(name='never (weights test)', kwargs={ 'text': 'Never', 'logic': [2, 3] }) stack.add_link(x='q2b', y=['@'], views=xnets.subset( ['ever (weights test)', 'never (weights test)']), weights=['weight_b']) # Get list of views created views_present = stack.describe(index=['view']) # Test that the expected views were all created self.assertNotIn('x|frequency|x[(1,2)]:y|||ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(1,2)]:y|y||ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y||weight_b|ever (weights test)', views_present) self.assertIn('x|frequency|x[(1,2)]:y|y|weight_b|ever (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|||never (weights test)', views_present) self.assertNotIn('x|frequency|x[(2,3)]:y|y||never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y||weight_b|never (weights test)', views_present) self.assertIn('x|frequency|x[(2,3)]:y|y|weight_b|never (weights test)', views_present)