6464from sdc .functions .numpy_like import getitem_by_mask
6565from sdc .datatypes .common_functions import _sdc_take , sdc_reindex_series
6666from sdc .utilities .prange_utils import parallel_chunks
67+ from sdc .functions .numpy_like import find_idx
6768
6869
6970@sdc_overload_attribute (DataFrameType , 'index' )
@@ -1876,6 +1877,58 @@ def _df_getitem_unicode_idx_impl(self, idx):
18761877 ty_checker .raise_exc (idx , expected_types , 'idx' )
18771878
18781879
1880+ def df_getitem_single_label_loc_codegen (self , idx ):
1881+ """
1882+ Example of generated implementation:
1883+ def _df_getitem_single_label_loc_impl(self, idx):
1884+ idx_list = find_idx(self._dataframe._index, idx)
1885+ data_0 = _sdc_take(self._dataframe._data[0], idx_list)
1886+ res_data_0 = pandas.Series(data_0)
1887+ data_1 = _sdc_take(self._dataframe._data[1], idx_list)
1888+ res_data_1 = pandas.Series(data_1)
1889+ if len(idx_list) < 1:
1890+ raise KeyError('Index is not in the DataFrame')
1891+ new_index = _sdc_take(self._dataframe._index, idx_list)
1892+ return pandas.DataFrame({"A": res_data_0, "B": res_data_1}, index=new_index)
1893+ """
1894+ if isinstance (self .index , types .NoneType ):
1895+ fill_list = [' idx_list = numpy.array([idx])' ]
1896+ new_index = [' new_index = numpy.array([idx])' ]
1897+
1898+ else :
1899+ fill_list = [' idx_list = find_idx(self._dataframe._index, idx)' ]
1900+ new_index = [' new_index = _sdc_take(self._dataframe._index, idx_list)' ]
1901+
1902+ fill_list_text = '\n ' .join (fill_list )
1903+ new_index_text = '\n ' .join (new_index )
1904+ func_lines = ['def _df_getitem_single_label_loc_impl(self, idx):' ,
1905+ f'{ fill_list_text } ' ]
1906+ results = []
1907+ for i , c in enumerate (self .columns ):
1908+ data = f'data_{ i } '
1909+ index_in_list = f'index_in_list_{ i } '
1910+ res_data = f'res_data_{ i } '
1911+ func_lines += [f' { data } = _sdc_take(self._dataframe._data[{ i } ], idx_list)' ,
1912+ f' { res_data } = pandas.Series({ data } )' ]
1913+ results .append ((c , res_data ))
1914+
1915+ func_lines += [' if len(idx_list) < 1:' ,
1916+ " raise KeyError('Index is not in the DataFrame')" ]
1917+
1918+ data = ', ' .join (f'"{ col } ": { data } ' for col , data in results )
1919+ func_lines += [f'{ new_index_text } ' ,
1920+ f' return pandas.DataFrame({{{ data } }}, index=new_index)' ]
1921+
1922+ func_text = '\n ' .join (func_lines )
1923+ global_vars = {'pandas' : pandas , 'numpy' : numpy ,
1924+ 'numba' : numba ,
1925+ '_sdc_take' : _sdc_take ,
1926+ 'find_idx' : find_idx ,
1927+ 'KeyError' : KeyError }
1928+
1929+ return func_text , global_vars
1930+
1931+
18791932def df_getitem_int_iloc_codegen (self , idx ):
18801933 """
18811934 Example of generated implementation:
@@ -2010,6 +2063,9 @@ def _df_getitem_list_bool_iloc_impl(self, idx):
20102063 return func_text , global_vars
20112064
20122065
2066+ gen_df_getitem_loc_single_label_impl = gen_impl_generator (
2067+ df_getitem_single_label_loc_codegen , '_df_getitem_single_label_loc_impl' )
2068+
20132069gen_df_getitem_iloc_int_impl = gen_impl_generator (
20142070 df_getitem_int_iloc_codegen , '_df_getitem_int_iloc_impl' )
20152071
@@ -2030,6 +2086,13 @@ def sdc_pandas_dataframe_accessor_getitem(self, idx):
20302086
20312087 accessor = self .accessor .literal_value
20322088
2089+ if accessor == 'loc' :
2090+ if isinstance (idx , (types .Integer , types .UnicodeType , types .StringLiteral )):
2091+ return gen_df_getitem_loc_single_label_impl (self .dataframe , idx )
2092+
2093+ ty_checker = TypeChecker ('Attribute loc().' )
2094+ ty_checker .raise_exc (idx , 'int or str' , 'idx' )
2095+
20332096 if accessor == 'iat' :
20342097 if isinstance (idx , types .Tuple ) and isinstance (idx [1 ], types .Literal ):
20352098 col = idx [1 ].literal_value
@@ -2181,6 +2244,57 @@ def sdc_pandas_dataframe_iat_impl(self):
21812244 return sdc_pandas_dataframe_iat_impl
21822245
21832246
2247+ @sdc_overload_attribute (DataFrameType , 'loc' )
2248+ def sdc_pandas_dataframe_loc (self ):
2249+ """
2250+ Intel Scalable Dataframe Compiler User Guide
2251+ ********************************************
2252+
2253+ Pandas API: pandas.DataFrame.loc
2254+
2255+ Limitations
2256+ -----------
2257+ - Loc always returns Dataframe.
2258+ - Parameter ``idx`` is supported only to be a single value, e.g. :obj:`df.loc['A']`.
2259+
2260+ Examples
2261+ --------
2262+ .. literalinclude:: ../../../examples/dataframe/dataframe_loc.py
2263+ :language: python
2264+ :lines: 36-
2265+ :caption: Access a group of rows and columns by label(s) or a boolean array.
2266+ :name: ex_dataframe_loc
2267+
2268+ .. command-output:: python ./dataframe/dataframe_loc.py
2269+ :cwd: ../../../examples
2270+
2271+ .. seealso::
2272+ :ref:`DataFrame.at <pandas.DataFrame.at>`
2273+ Access a single value for a row/column label pair.
2274+ :ref:`DataFrame.iloc <pandas.DataFrame.iloc>`
2275+ Access group of rows and columns by integer position(s).
2276+ :ref:`DataFrame.xs <pandas.DataFrame.xs>`
2277+ Returns a cross-section (row(s) or column(s)) from the Series/DataFrame.
2278+ :ref:`Series.loc <pandas.Series.loc>`
2279+ Access group of values using labels.
2280+
2281+ Intel Scalable Dataframe Compiler Developer Guide
2282+ *************************************************
2283+ Pandas DataFrame method :meth:`pandas.DataFrame.loc` implementation.
2284+
2285+ .. only:: developer
2286+ Test: python -m sdc.runtests -k sdc.tests.test_dataframe.TestDataFrame.test_df_loc*
2287+ """
2288+
2289+ ty_checker = TypeChecker ('Attribute loc().' )
2290+ ty_checker .check (self , DataFrameType )
2291+
2292+ def sdc_pandas_dataframe_loc_impl (self ):
2293+ return sdc .datatypes .hpat_pandas_dataframe_getitem_types .dataframe_getitem_accessor_init (self , 'loc' )
2294+
2295+ return sdc_pandas_dataframe_loc_impl
2296+
2297+
21842298@sdc_overload_method (DataFrameType , 'pct_change' )
21852299def pct_change_overload (df , periods = 1 , fill_method = 'pad' , limit = None , freq = None ):
21862300 """
0 commit comments