2828import operator
2929
3030import numba
31+ from typing import NamedTuple
3132from numba import types , cgutils
3233from numba .extending import (models , register_model , lower_cast , infer_getattr ,
3334 type_callable , infer , overload , intrinsic ,
@@ -52,6 +53,11 @@ def generic_resolve(self, df, attr):
5253 return SeriesType (arr_typ .dtype , arr_typ , df .index , True )
5354
5455
56+ class ColumnId (NamedTuple ):
57+ type_id : int
58+ col_type_id : int
59+
60+
5561@intrinsic
5662def init_dataframe (typingctx , * args ):
5763 """Create a DataFrame with provided data, index and columns values.
@@ -66,6 +72,28 @@ def init_dataframe(typingctx, *args):
6672 index_typ = args [n_cols ]
6773 column_names = tuple (a .literal_value for a in args [n_cols + 1 :])
6874
75+ # Define df structure, map column name to column position ex. {'A': (0,0), 'B': (1,0), 'C': (0,1)}
76+ df_structure = {}
77+ # Store unique types of columns ex. {'int64': (0, [0, 2]), 'float64': (1, [1])}
78+ data_typs_map = {}
79+ types_order = []
80+ type_id = 0
81+ for col_id , col_typ in enumerate (data_typs ):
82+ col_name = column_names [col_id ]
83+
84+ if col_typ not in data_typs_map :
85+ data_typs_map [col_typ ] = (type_id , [col_id ])
86+ # The first column in each type always has 0 index
87+ df_structure [col_name ] = ColumnId (type_id , 0 )
88+ types_order .append (col_typ )
89+ type_id += 1
90+ else :
91+ # Get index of column in list of types
92+ type_idx , col_indices = data_typs_map [col_typ ]
93+ col_idx_list = len (col_indices )
94+ df_structure [col_name ] = ColumnId (type_idx , col_idx_list )
95+ col_indices .append (col_id )
96+
6997 def codegen (context , builder , signature , args ):
7098 in_tup = args [0 ]
7199 data_arrs = [builder .extract_value (in_tup , i ) for i in range (n_cols )]
@@ -76,15 +104,23 @@ def codegen(context, builder, signature, args):
76104 dataframe = cgutils .create_struct_proxy (
77105 signature .return_type )(context , builder )
78106
107+ data_list_type = [types .List (typ ) for typ in types_order ]
108+
109+ data_lists = []
110+ for typ_id , typ in enumerate (types_order ):
111+ data_list_typ = context .build_list (builder , data_list_type [typ_id ],
112+ [data_arrs [data_id ] for data_id in data_typs_map [typ ][1 ]])
113+ data_lists .append (data_list_typ )
114+
79115 data_tup = context .make_tuple (
80- builder , types .Tuple (data_typs ), data_arrs )
81- column_tup = context . make_tuple (
82- builder , types .UniTuple (string_type , n_cols ), column_strs )
83- zero = context .get_constant ( types . int8 , 0 )
116+ builder , types .Tuple (data_list_type ), data_lists )
117+
118+ col_list_type = types .List (string_type )
119+ column_list = context .build_list ( builder , col_list_type , column_strs )
84120
85121 dataframe .data = data_tup
86122 dataframe .index = index
87- dataframe .columns = column_tup
123+ dataframe .columns = column_list
88124 dataframe .parent = context .get_constant_null (types .pyobject )
89125
90126 # increase refcount of stored values
@@ -97,7 +133,7 @@ def codegen(context, builder, signature, args):
97133
98134 return dataframe ._getvalue ()
99135
100- ret_typ = DataFrameType (data_typs , index_typ , column_names )
136+ ret_typ = DataFrameType (data_typs , index_typ , column_names , df_structure = df_structure )
101137 sig = signature (ret_typ , types .Tuple (args ))
102138 return sig , codegen
103139
0 commit comments