#NEWLINE# @ utils . allow_tableset_proxy #NEWLINE# def denormalize( self , key = None , property_column = 'property' , value_column = 'value' , default_value = utils . default , column_types = None ) : #NEWLINE# #INDENT# '\n    Create a new table with row values converted into columns.\n\n    For example:\n\n    +---------+-----------+---------+\n    |  name   | property  | value   |\n    +=========+===========+=========+\n    |  Jane   | gender    | female  |\n    +---------+-----------+---------+\n    |  Jane   | race      | black   |\n    +---------+-----------+---------+\n    |  Jane   | age       | 24      |\n    +---------+-----------+---------+\n    |  ...    |  ...      |  ...    |\n    +---------+-----------+---------+\n\n    Can be denormalized so that each unique value in `field` becomes a\n    column with `value` used for its values.\n\n    +---------+----------+--------+-------+\n    |  name   | gender   | race   | age   |\n    +=========+==========+========+=======+\n    |  Jane   | female   | black  | 24    |\n    +---------+----------+--------+-------+\n    |  Jack   | male     | white  | 35    |\n    +---------+----------+--------+-------+\n    |  Joe    | male     | black  | 28    |\n    +---------+----------+--------+-------+\n\n    If one or more keys are specified then the resulting table will\n    automatically have :code:`row_names` set to those keys.\n\n    This is the opposite of :meth:`.Table.normalize`.\n\n    :param key:\n        A column name or a sequence of column names that should be\n        maintained as they are in the normalized table. Typically these\n        are the tables unique identifiers and any metadata about them. Or,\n        :code:`None` if there are no key columns.\n    :param field_column:\n        The column whose values should become column names in the new table.\n    :param property_column:\n        The column whose values should become the values of the property\n        columns in the new table.\n    :param default_value:\n        Value to be used for missing values in the pivot table. If not\n        specified :code:`Decimal(0)` will be used for aggregations that\n        return :class:`.Number` data and :code:`None` will be used for\n        all others.\n    :param column_types:\n        A sequence of column types with length equal to number of unique\n        values in field_column or an instance of :class:`.TypeTester`.\n        Defaults to a generic :class:`.TypeTester`.\n    :returns:\n        A new :class:`.Table`.\n    ' #NEWLINE# from agate.table import Table #NEWLINE# if ( key is None ) : #NEWLINE# #INDENT# key = [ ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( not utils . issequence ( key ) ) : #NEWLINE# #INDENT# key = [ key ] #NEWLINE# #UNINDENT# #UNINDENT# field_names = [ ] #NEWLINE# row_data = OrderedDict ( ) #NEWLINE# for row in self . rows : #NEWLINE# #INDENT# row_key = tuple ( ( row [ k ] for k in key ) ) #NEWLINE# if ( row_key not in row_data ) : #NEWLINE# #INDENT# row_data [ row_key ] = OrderedDict ( ) #NEWLINE# #UNINDENT# f = six . text_type ( row [ property_column ] ) #NEWLINE# v = row [ value_column ] #NEWLINE# if ( f not in field_names ) : #NEWLINE# #INDENT# field_names . append ( f ) #NEWLINE# #UNINDENT# row_data [ row_key ] [ f ] = v #NEWLINE# #UNINDENT# if ( default_value == utils . default ) : #NEWLINE# #INDENT# if isinstance ( self . columns [ value_column ] . data_type , Number ) : #NEWLINE# #INDENT# default_value = Decimal ( 0 ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# default_value = None #NEWLINE# #UNINDENT# #UNINDENT# new_column_names = ( key + field_names ) #NEWLINE# new_rows = [ ] #NEWLINE# row_names = [ ] #NEWLINE# for ( k , v ) in row_data . items ( ) : #NEWLINE# #INDENT# row = list ( k ) #NEWLINE# if ( len ( k ) == 1 ) : #NEWLINE# #INDENT# row_names . append ( k [ 0 ] ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# row_names . append ( k ) #NEWLINE# #UNINDENT# for f in field_names : #NEWLINE# #INDENT# if ( f in v ) : #NEWLINE# #INDENT# row . append ( v [ f ] ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# row . append ( default_value ) #NEWLINE# #UNINDENT# #UNINDENT# new_rows . append ( Row ( row , new_column_names ) ) #NEWLINE# #UNINDENT# key_column_types = [ self . column_types [ self . column_names . index ( name ) ] for name in key ] #NEWLINE# if ( ( column_types is None ) or isinstance ( column_types , TypeTester ) ) : #NEWLINE# #INDENT# tester = ( TypeTester ( ) if ( column_types is None ) else column_types ) #NEWLINE# force_update = dict ( zip ( key , key_column_types ) ) #NEWLINE# force_update . update ( tester . _force ) #NEWLINE# tester . _force = force_update #NEWLINE# new_column_types = tester . run ( new_rows , new_column_names ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# new_column_types = ( key_column_types + list ( column_types ) ) #NEWLINE# #UNINDENT# return Table ( new_rows , new_column_names , new_column_types , row_names = row_names )