3737
3838from pandas .core .indexing import IndexingError
3939
40- from numba import types
40+ from numba import types , prange
4141from numba .special import literally
4242from numba .typed import List , Dict
4343from numba .errors import TypingError
@@ -1877,6 +1877,35 @@ def _df_getitem_unicode_idx_impl(self, idx):
18771877 ty_checker .raise_exc (idx , expected_types , 'idx' )
18781878
18791879
1880+ def df_getitem_tuple_at_codegen (self , row , col ):
1881+ """
1882+ Example of generated implementation:
1883+ def _df_getitem_tuple_at_impl(self, idx):
1884+ row, _ = idx
1885+ data = self._dataframe._data[1]
1886+ res_data = pandas.Series(data, index=self._dataframe.index)
1887+ return res_data.at[row]
1888+ """
1889+ func_lines = ['def _df_getitem_tuple_at_impl(self, idx):' ,
1890+ ' row, _ = idx' ]
1891+ check = False
1892+ for i in range (len (self .columns )):
1893+ if self .columns [i ] == col :
1894+ check = True
1895+ func_lines += [
1896+ f' data = self._dataframe._data[{ i } ]' ,
1897+ f' res_data = pandas.Series(data, index=self._dataframe.index)' ,
1898+ ' return res_data.at[row]' ,
1899+ ]
1900+ if check == False : # noqa
1901+ raise KeyError ('Column is not in the DataFrame' )
1902+
1903+ func_text = '\n ' .join (func_lines )
1904+ global_vars = {'pandas' : pandas }
1905+
1906+ return func_text , global_vars
1907+
1908+
18801909def df_getitem_single_label_loc_codegen (self , idx ):
18811910 """
18821911 Example of generated implementation:
@@ -2063,6 +2092,15 @@ def _df_getitem_list_bool_iloc_impl(self, idx):
20632092 return func_text , global_vars
20642093
20652094
2095+ def gen_df_getitem_tuple_at_impl (self , row , col ):
2096+ func_text , global_vars = df_getitem_tuple_at_codegen (self , row , col )
2097+ loc_vars = {}
2098+ exec (func_text , global_vars , loc_vars )
2099+ _reduce_impl = loc_vars ['_df_getitem_tuple_at_impl' ]
2100+
2101+ return _reduce_impl
2102+
2103+
20662104gen_df_getitem_loc_single_label_impl = gen_impl_generator (
20672105 df_getitem_single_label_loc_codegen , '_df_getitem_single_label_loc_impl' )
20682106
@@ -2086,6 +2124,21 @@ def sdc_pandas_dataframe_accessor_getitem(self, idx):
20862124
20872125 accessor = self .accessor .literal_value
20882126
2127+ if accessor == 'at' :
2128+ num_idx = isinstance (idx [0 ], types .Number ) and isinstance (self .dataframe .index , (types .Array , types .NoneType ))
2129+ str_idx = (isinstance (idx [0 ], (types .UnicodeType , types .StringLiteral ))
2130+ and isinstance (self .dataframe .index , StringArrayType ))
2131+ if isinstance (idx , types .Tuple ) and isinstance (idx [1 ], types .StringLiteral ):
2132+ if num_idx or str_idx :
2133+ row = idx [0 ]
2134+ col = idx [1 ].literal_value
2135+ return gen_df_getitem_tuple_at_impl (self .dataframe , row , col )
2136+
2137+ raise TypingError ('Attribute at(). The row parameter type ({}) is different from the index type\
2138+ ({})' .format (type (idx [0 ]), type (self .dataframe .index )))
2139+
2140+ raise TypingError ('Attribute at(). The index must be a row and literal column. Given: {}' .format (idx ))
2141+
20892142 if accessor == 'loc' :
20902143 if isinstance (idx , (types .Integer , types .UnicodeType , types .StringLiteral )):
20912144 return gen_df_getitem_loc_single_label_impl (self .dataframe , idx )
@@ -2244,6 +2297,58 @@ def sdc_pandas_dataframe_iat_impl(self):
22442297 return sdc_pandas_dataframe_iat_impl
22452298
22462299
2300+ @sdc_overload_attribute (DataFrameType , 'at' )
2301+ def sdc_pandas_dataframe_at (self ):
2302+ """
2303+ Intel Scalable Dataframe Compiler User Guide
2304+ ********************************************
2305+
2306+ Limitations
2307+ -----------
2308+ - ``Dataframe.at`` always returns ``array``.
2309+ - Parameter ``column`` in ``idx`` must be a literal value.
2310+
2311+ Pandas API: pandas.DataFrame.at
2312+
2313+ Examples
2314+ --------
2315+ .. literalinclude:: ../../../examples/dataframe/dataframe_at.py
2316+ :language: python
2317+ :lines: 28-
2318+ :caption: Access a single value for a row/column label pair.
2319+ :name: ex_dataframe_at
2320+
2321+ .. command-output:: python ./dataframe/dataframe_at.py
2322+ :cwd: ../../../examples
2323+
2324+ .. seealso::
2325+
2326+ :ref:`DataFrame.iat <pandas.DataFrame.iat>`
2327+ Access a single value for a row/column pair by integer position.
2328+
2329+ :ref:`DataFrame.loc <pandas.DataFrame.loc>`
2330+ Access a group of rows and columns by label(s).
2331+
2332+ :ref:`Series.at <pandas.Series.at>`
2333+ Access a single value using a label.
2334+
2335+ Intel Scalable Dataframe Compiler Developer Guide
2336+ *************************************************
2337+ Pandas DataFrame method :meth:`pandas.DataFrame.at` implementation.
2338+
2339+ .. only:: developer
2340+ Test: python -m sdc.runtests -k sdc.tests.test_dataframe.TestDataFrame.test_df_at*
2341+ """
2342+
2343+ ty_checker = TypeChecker ('Attribute at().' )
2344+ ty_checker .check (self , DataFrameType )
2345+
2346+ def sdc_pandas_dataframe_at_impl (self ):
2347+ return dataframe_getitem_accessor_init (self , 'at' )
2348+
2349+ return sdc_pandas_dataframe_at_impl
2350+
2351+
22472352@sdc_overload_attribute (DataFrameType , 'loc' )
22482353def sdc_pandas_dataframe_loc (self ):
22492354 """
0 commit comments