"AttributeError: 'DataFrame' object has no attribute 'ix'" when using .loc or .iloc to replace .ix

29 Views Asked by At

I have been asked to revive a Spearman Correlation code that requires a module that was authored by someone else and hasn't been updated since 2018 (module name is fouriertransform: https://github.com/FluvialSeds/fouriertransform) to work on Python 3.11.7. Since publication, the .ix indexing function from the pandas module has been deprecated. I keep receiving "AttributeError: 'DataFrame' object has no attribute 'ix'". This error populates when I change the .ix to .loc and to .iloc, as suggested for other users encountering the same problem with using .ix. I don't know what else to try, as I'm very new to Python (and do very little code writing). I'm unsure if this matters, but I am editing this code in Sublime Text and running it in IPython (both were recommended by my supervisor), but the files are registering as modified in the Windows File Explorer and the changes do show up on the errors.

My code has me import a bunch of files, then extracts the relevant data from those files and does some statistical analyses on the extracted data using the fouriertransform module. The error comes from generating a summary of the extracted data.

Original fouriertransform module crosstable_helper.py code:

#define function to calculate modified aromaticity index
def _calc_pct(ct, cols, weights):
    '''
    Calculates percentages for generating a summary table.

    Parameters
    ----------
    ct : ft.CrossTable
        ``CrossTable`` instance containing the formulae of interest.

    cols : list
        List of column names to be calculated (required input for indexing
        purposes. Columns get mis-aligned if omitted).

    weights : str
        String of weights to use for %RA calculates, either compound
        categories or classes. Inputed from the _gen_sum_tab function.

    Returns
    -------
    pcts : pd.DataFrame
        Resulting dataframe of calculated percentages for each sample.

    Raises
    ------
    AssertionError
        If percentages do not add up to 100.

    '''

    #call intensites df for shorthand
    df = ct.intensities

    #calculate totals
    tot_N = np.sum(df > 0)
    tot_int = np.sum(df)

    #extract class / category names
    names = weights.unique()

    #make empty dataframe of results
    pcts = pd.DataFrame(index = ct.sam_names, columns = cols)

    #loop through each class / category and store results
    for n in names:

        #extract compounds within class/category
        ind = np.where(weights == n)[0]
        cforms = df.ix[ind]

        #calculate class/category formula numbers and intensities
        c_N = np.sum(cforms > 0)
        c_int = np.sum(cforms)

        #calculate percentages
        c_pct_N = 100*c_N/tot_N
        c_pct_RA = 100*c_int/tot_int

        #store results
        pcts[n + '_%N'] = c_pct_N
        pcts[n + '_%RA'] = c_pct_RA

    #assert that it all adds up to 200 (sum of N-based and RA-based)
    assert (pcts.sum(axis = 1) - 200 < 1e-6).all(), \
        'Calculated percentages do not add up within 1 part per million!' \
        ' Something is not assigned a compound class / category!'

    return pcts

Original Error (currently I am ignoring the FutureWarnings):

In [18]: sum_tab = ct.generate_summary()
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-18-6dabb3fee1af> in ?()
----> 1 sum_tab = ct.generate_summary()

~\anaconda3\Lib\site-packages\fouriertransform\crosstable.py in ?(self)
    462                 ----------
    463                 Santi-Temkiv et al. (2013), PLoS One, doi:10.1371/journal.pone.0053550.
    464                 '''
    465
--> 466                 sum_df = _gen_sum_tab(self)
    467
    468                 return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct)
   1022
   1023         sum_df['AImod_RA'] = \
   1024                 np.sum(ct.intensities.multiply(ct.AImod, axis = 0))/tot_int
   1025
-> 1026         sum_df[cls_mets] = _calc_pct(ct, cls_mets, ct.cmpd_class)
   1027         sum_df[cat_mets] = _calc_pct(ct, cat_mets, ct.cmpd_cat)
   1028
   1029         return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct, cols, weights)
    524         for n in names:
    525
    526                 #extract compounds within class/category
    527                 ind = np.where(weights == n)[0]
--> 528                 cforms = df.ix[ind]
    529
    530                 #calculate class/category formula numbers and intensities
    531                 c_N = np.sum(cforms > 0)

~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
   6200             and name not in self._accessors
   6201             and self._info_axis._can_hold_identifiers_and_holds_name(name)
   6202         ):
   6203             return self[name]
-> 6204         return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'ix'

Fix attempt #1, changed .ix in the crosstable_helper.py file to .loc:

In [19]: sum_tab = ct.generate_summary()
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-19-6dabb3fee1af> in ?()
----> 1 sum_tab = ct.generate_summary()

~\anaconda3\Lib\site-packages\fouriertransform\crosstable.py in ?(self)
    462                 ----------
    463                 Santi-Temkiv et al. (2013), PLoS One, doi:10.1371/journal.pone.0053550.
    464                 '''
    465
--> 466                 sum_df = _gen_sum_tab(self)
    467
    468                 return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct)
   1022
   1023         sum_df['AImod_RA'] = \
   1024                 np.sum(ct.intensities.multiply(ct.AImod, axis = 0))/tot_int
   1025
-> 1026         sum_df[cls_mets] = _calc_pct(ct, cls_mets, ct.cmpd_class)
   1027         sum_df[cat_mets] = _calc_pct(ct, cat_mets, ct.cmpd_cat)
   1028
   1029         return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct, cols, weights)
    524         for n in names:
    525
    526                 #extract compounds within class/category
    527                 ind = np.where(weights == n)[0]
--> 528                 cforms = df.loc[ind]
    529
    530                 #calculate class/category formula numbers and intensities
    531                 c_N = np.sum(cforms > 0)

~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
   6200             and name not in self._accessors
   6201             and self._info_axis._can_hold_identifiers_and_holds_name(name)
   6202         ):
   6203             return self[name]
-> 6204         return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'ix'

Fix attempt #2, changed .loc to .iloc in crosstable_helper.py file

In [21]: sum_tab = ct.generate_summary()
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
C:\Users\peter\anaconda3\Lib\site-packages\numpy\core\fromnumeric.py:86: FutureWarning: The behavior of DataFrame.sum with axis=None is deprecated, in a future version this will reduce over both axes and return a scalar. To retain the old behavior, pass axis=0 (or do not pass axis)
  return reduction(axis=axis, out=out, **passkwargs)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-21-6dabb3fee1af> in ?()
----> 1 sum_tab = ct.generate_summary()

~\anaconda3\Lib\site-packages\fouriertransform\crosstable.py in ?(self)
    462                 ----------
    463                 Santi-Temkiv et al. (2013), PLoS One, doi:10.1371/journal.pone.0053550.
    464                 '''
    465
--> 466                 sum_df = _gen_sum_tab(self)
    467
    468                 return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct)
   1022
   1023         sum_df['AImod_RA'] = \
   1024                 np.sum(ct.intensities.multiply(ct.AImod, axis = 0))/tot_int
   1025
-> 1026         sum_df[cls_mets] = _calc_pct(ct, cls_mets, ct.cmpd_class)
   1027         sum_df[cat_mets] = _calc_pct(ct, cat_mets, ct.cmpd_cat)
   1028
   1029         return sum_df

~\anaconda3\Lib\site-packages\fouriertransform\crosstable_helper.py in ?(ct, cols, weights)
    524         for n in names:
    525
    526                 #extract compounds within class/category
    527                 ind = np.where(weights == n)[0]
--> 528                 cforms = df.iloc[ind]
    529
    530                 #calculate class/category formula numbers and intensities
    531                 c_N = np.sum(cforms > 0)

~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
   6200             and name not in self._accessors
   6201             and self._info_axis._can_hold_identifiers_and_holds_name(name)
   6202         ):
   6203             return self[name]
-> 6204         return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'ix'

I think if I can clear this attribute error, I should be able to get the summary table. I'm happy to provide the data files and script files I'm working with if that would be more helpful.

EDIT: reloading the module worked! I didn't realize that was an option.

0

There are 0 best solutions below