Python Pandas: Función Drop Duplicates - Comportamiento inusual

El error -> TypeError: unhashable type: 'list' desaparece después de guardar el marco de datos y cargarlo de nuevo...

Ambos marcos de datos [guardados y cargados, generados] tienen los mismos tipos de d ...

Reproducibles ->

--> import pandas as pd
--> l1 = [[1], [1], [1], [1], [1], [1], [1], [1], [6], [1], [6], [1], [6], [6], [6], [6], [6], [6], [6], [6], [6]]

## len(l1) is 21 ##

--> l2 = ['a']*21
--> l3 = ['c']*10 + ['d']*10 + ['e']
--> df = pd.DataFrame()
--> df['col1'], df['col2'], df['col3'] = l1, l3, l2
--> df
        col1 col2 col3
        0   [1]    c    a
        1   [1]    c    a
        2   [1]    c    a
        3   [1]    c    a
        4   [1]    c    a
        5   [1]    c    a
        6   [1]    c    a
        7   [1]    c    a
        8   [6]    c    a
        9   [1]    c    a
        10  [6]    d    a
        11  [1]    d    a
        12  [6]    d    a
        13  [6]    d    a
        14  [6]    d    a
        15  [6]    d    a
        16  [6]    d    a
        17  [6]    d    a
        18  [6]    d    a
        19  [6]    d    a
        20  [6]    e    a

--> df.dtypes
        col1    object
        col2    object
        col3    object
        dtype: object

--> df.drop_duplicates(subset=['col1', 'col2', 'col3'], keep='last', inplace=True)
        
        ## TypeError: unhashable type: 'list' ##

## Here if I save it as an excel and load again, then this error does not come up ... ##

--> df.to_excel('test.xlsx')
--> df_ = pd.read_excel('test.xlsx')
--> df_.dtypes
        Unnamed: 0     int64
        col1    object
        col2    object
        col3    object
        dtype: object
--> df_.drop_duplicates(subset=['col1', 'col2', 'col3'], keep='last', inplace=True)
--> df_
         Unnamed: 0 col1 col2 col3
        8       8   [6]    c    a
        9       9   [1]    c    a
        11      11  [1]    d    a
        19      19  [6]    d    a
        20      20  [6]    e    a

¿Este comportamiento tiene una explicación?

Rastreo extendido del problema

Rastreo (llamadas recientes más última):

Archivo "", línea 1, en

Archivo "C:\Users\Agnij\Anaconda3\lib\site-packages\pandas\core\frame.py", línea 4811, en drop_duplicates

duplicado = self.duplicado(subconjunto, mantener=mantener)

Archivo "C:\Users\Agnij\Anaconda3\lib\site-packages\pandas\core\frame.py", línea 4888, en etiquetas duplicadas, forma = map(list, zip(*map(f, vals)))

Archivo "C:\Users\Agnij\Anaconda3\lib\site-packages\pandas\core\frame.py", línea 4863, en f vals, size_hint=min(len(self), _SIZE_HINT_LIMIT)

Archivo "C:\Users\Agnij\Anaconda3\lib\site-packages\pandas\core\algorithms.py", línea 636, en valores factorizados, na_sentinel=na_sentinel, size_hint=size_hint, na_value=na_value

Archivo "C:\Users\Agnij\Anaconda3\lib\site-packages\pandas\core\algorithms.py", línea 484, en _factorize_array uniques, codes = table.factorize(values, na_sentinel=na_sentinel, na_value=na_value)

Archivo "pandas_libs\hashtable_class_helper.pxi", línea 1815, en pandas._libs.hashtable.PyObjectHashTable.factorize

Archivo "pandas_libs\hashtable_class_helper.pxi", línea 1731, en pandas._libs.hashtable.PyObjectHashTable._unique

Answer

drop_duplicates hash los objetos para realizar un seguimiento de cuáles se han visto o no, de manera eficiente.

listLos s no se pueden modificar (ya que son mutables), por lo que no puede usar drop_duplicates en ellos directamente. Cuando guarda y carga los datos, es probable que se conviertan en una cadena, lo que permite calcular el hash.

Para solucionar el problema, puede convertir las listas en tuplas, que se pueden modificar:

df['col1'] = df['col1'].apply(tuple)
# now this runs with no error
df.drop_duplicates(subset=['col1', 'col2', 'col3'], keep='last', inplace=True)

Porque aunque ambas columnas son objetos de tipo d, los elementos en ellas son de diferentes tipos:

>>> df.loc[0,'col1']
[1]


>>> df_.loc[0, 'col1']
'[1]'

Dado que las cadenas se pueden modificar, no ve el error que tenía antes con las listas.