¿Qué significa `ValueError: no se puede reindexar desde un eje duplicado`?

254

Recibo un mensaje ValueError: cannot reindex from a duplicate axiscuando intento establecer un índice en un valor determinado. Traté de reproducir esto con un ejemplo simple, pero no pude hacerlo.

Aquí está mi sesión dentro de ipdbtrace. Tengo un DataFrame con índice de cadena y columnas enteras, valores flotantes. Sin embargo, cuando intento crear un sumíndice para la suma de todas las columnas, recibo un ValueError: cannot reindex from a duplicate axiserror. Creé un pequeño DataFrame con las mismas características, pero no pude reproducir el problema, ¿qué me podría perder?

Realmente no entiendo qué ValueError: cannot reindex from a duplicate axissignifica, ¿qué significa este mensaje de error? Tal vez esto me ayude a diagnosticar el problema, y ​​esta es la parte más responsable de mi pregunta.

ipdb> type(affinity_matrix)
<class 'pandas.core.frame.DataFrame'>
ipdb> affinity_matrix.shape
(333, 10)
ipdb> affinity_matrix.columns
Int64Index([9315684, 9315597, 9316591, 9320520, 9321163, 9320615, 9321187, 9319487, 9319467, 9320484], dtype='int64')
ipdb> affinity_matrix.index
Index([u'001', u'002', u'003', u'004', u'005', u'008', u'009', u'010', u'011', u'014', u'015', u'016', u'018', u'020', u'021', u'022', u'024', u'025', u'026', u'027', u'028', u'029', u'030', u'032', u'033', u'034', u'035', u'036', u'039', u'040', u'041', u'042', u'043', u'044', u'045', u'047', u'047', u'048', u'050', u'053', u'054', u'055', u'056', u'057', u'058', u'059', u'060', u'061', u'062', u'063', u'065', u'067', u'068', u'069', u'070', u'071', u'072', u'073', u'074', u'075', u'076', u'077', u'078', u'080', u'082', u'083', u'084', u'085', u'086', u'089', u'090', u'091', u'092', u'093', u'094', u'095', u'096', u'097', u'098', u'100', u'101', u'103', u'104', u'105', u'106', u'107', u'108', u'109', u'110', u'111', u'112', u'113', u'114', u'115', u'116', u'117', u'118', u'119', u'121', u'122', ...], dtype='object')

ipdb> affinity_matrix.values.dtype
dtype('float64')
ipdb> 'sums' in affinity_matrix.index
False

Aquí está el error:

ipdb> affinity_matrix.loc['sums'] = affinity_matrix.sum(axis=0)
*** ValueError: cannot reindex from a duplicate axis

Traté de reproducir esto con un ejemplo simple, pero fallé

In [32]: import pandas as pd

In [33]: import numpy as np

In [34]: a = np.arange(35).reshape(5,7)

In [35]: df = pd.DataFrame(a, ['x', 'y', 'u', 'z', 'w'], range(10, 17))

In [36]: df.values.dtype
Out[36]: dtype('int64')

In [37]: df.loc['sums'] = df.sum(axis=0)

In [38]: df
Out[38]: 
      10  11  12  13  14  15   16
x      0   1   2   3   4   5    6
y      7   8   9  10  11  12   13
u     14  15  16  17  18  19   20
z     21  22  23  24  25  26   27
w     28  29  30  31  32  33   34
sums  70  75  80  85  90  95  100
Akavall
fuente
1
¿Hay alguna posibilidad de que ofuscaste los nombres de columna reales de tu matriz de afinidad? (es decir, reemplazó los valores reales con algo más para ocultar información confidencial)
Korem
@Korem, no creo que esto sea cierto, pero incluso si esto es cierto, ¿por qué esto causaría el error anterior?
Akavall
2
Normalmente veo esto cuando el índice asignado tiene valores duplicados. Como en su caso está asignando una fila, esperaba un duplicado en los nombres de las columnas. Por eso pregunté.
Korem
@Korem, de hecho, mis datos reales tenían valores de índice duplicados, y pude reproducir el error en el pequeño ejemplo cuando estaban presentes valores de índice duplicados. Respondiste completamente a mi pregunta. Gracias. ¿Te importa ponerlo como respuesta?
Akavall

Respuestas:

170

Este error generalmente aumenta cuando se une / asigna a una columna cuando el índice tiene valores duplicados. Como está asignando a una fila, sospecho que hay un valor duplicado en affinity_matrix.columns, tal vez no se muestra en su pregunta.

Korem
fuente
20
Para ser más exactos, en mi caso había un valor duplicado affinity_matrix.index, pero creo que este es el mismo concepto.
Akavall
24
Para aquellos que llegan a esto más adelante, indexsignifica ambos rowy column namespasé 20 minutos en el índice de la fila, pero resultó que obtuve nombres de columna duplicados que causaron este error.
Jason Goal
Para agregar a esto, me encontré con este error cuando intenté reindexar un marco de datos en una lista de columnas. Por extraño que parezca, mi duplicado estaba en mi marco de datos original, ¡así que asegúrese de verificar ambos!
m8_
163

Como han dicho otros, probablemente tenga valores duplicados en su índice original. Para encontrarlos haz esto:

df[df.index.duplicated()]

Mateo
fuente
39
Para eliminar filas con índices duplicados, use:df = df[~df.index.duplicated()]
tuomastik
44
Para DatetimeIndextramas de datos ed, puede resampleque la frecuencia deseada y luego tomar .first(), .mean()etc.
BallpointBen
28

Los índices con valores duplicados a menudo surgen si crea un DataFrame concatenando otros DataFrames. SI no le importa preservar los valores de su índice, y desea que sean valores únicos, cuando concatene los datos, establezca ignore_index=True.

Alternativamente, para sobrescribir su índice actual con uno nuevo, en lugar de usar df.reindex(), establezca:

df.index = new_index
Rebeku
fuente
8
Solía ignore_index = true para obtener el código para trabajar con tramas de datos concatenados
Gabi Lee
De hecho, ignore_index=Falsees el valor predeterminado; si usar la opción es cambiar appendel comportamiento, tendrá que ser porque lo configuró en True.
Jeffrey Benjamin Brown
17

Para las personas que todavía están luchando con este error, también puede suceder si accidentalmente crea una columna duplicada con el mismo nombre. Eliminar columnas duplicadas de esta manera:

df = df.loc[:,~df.columns.duplicated()]
Lengua de Parsel
fuente
12

Simplemente omita el error usando .valuesal final.

affinity_matrix.loc['sums'] = affinity_matrix.sum(axis=0).values
Hadij
fuente
¡Esto es exactamente lo que necesitaba! Solo trato de crear una nueva columna, pero tenía un índice con duplicados. Usando .valueshizo el truco
Paul Wildenhain
8

Me encontré con este error hoy cuando quería agregar una nueva columna como esta

df_temp['REMARK_TYPE'] = df.REMARK.apply(lambda v: 1 if str(v)!='nan' else 0)

Quería procesar la REMARKcolumna de df_temppara devolver 1 o 0. Sin embargo, escribí una variable incorrecta con df. Y devolvió un error como este:

----> 1 df_temp['REMARK_TYPE'] = df.REMARK.apply(lambda v: 1 if str(v)!='nan' else 0)

/usr/lib64/python2.7/site-packages/pandas/core/frame.pyc in __setitem__(self, key, value)
   2417         else:
   2418             # set column
-> 2419             self._set_item(key, value)
   2420 
   2421     def _setitem_slice(self, key, value):

/usr/lib64/python2.7/site-packages/pandas/core/frame.pyc in _set_item(self, key, value)
   2483 
   2484         self._ensure_valid_index(value)
-> 2485         value = self._sanitize_column(key, value)
   2486         NDFrame._set_item(self, key, value)
   2487 

/usr/lib64/python2.7/site-packages/pandas/core/frame.pyc in _sanitize_column(self, key, value, broadcast)
   2633 
   2634         if isinstance(value, Series):
-> 2635             value = reindexer(value)
   2636 
   2637         elif isinstance(value, DataFrame):

/usr/lib64/python2.7/site-packages/pandas/core/frame.pyc in reindexer(value)
   2625                     # duplicate axis
   2626                     if not value.index.is_unique:
-> 2627                         raise e
   2628 
   2629                     # other

ValueError: cannot reindex from a duplicate axis

Como puede ver, el código correcto debería ser

df_temp['REMARK_TYPE'] = df_temp.REMARK.apply(lambda v: 1 if str(v)!='nan' else 0)

Porque dfy df_temptiene un número diferente de filas. Entonces regresó ValueError: cannot reindex from a duplicate axis.

Espero que lo entiendas y mi respuesta puede ayudar a otras personas a depurar su código.

GoingMyWay
fuente
4

En mi caso, este error apareció no debido a valores duplicados, sino porque intenté unir una Serie más corta a un Marco de datos: ambos tenían el mismo índice, pero la Serie tenía menos filas (faltaban las primeras). Lo siguiente funcionó para mis propósitos:

df.head()
                          SensA
date                           
2018-04-03 13:54:47.274   -0.45
2018-04-03 13:55:46.484   -0.42
2018-04-03 13:56:56.235   -0.37
2018-04-03 13:57:57.207   -0.34
2018-04-03 13:59:34.636   -0.33

series.head()
date
2018-04-03 14:09:36.577    62.2
2018-04-03 14:10:28.138    63.5
2018-04-03 14:11:27.400    63.1
2018-04-03 14:12:39.623    62.6
2018-04-03 14:13:27.310    62.5
Name: SensA_rrT, dtype: float64

df = series.to_frame().combine_first(df)

df.head(10)
                          SensA  SensA_rrT
date                           
2018-04-03 13:54:47.274   -0.45        NaN
2018-04-03 13:55:46.484   -0.42        NaN
2018-04-03 13:56:56.235   -0.37        NaN
2018-04-03 13:57:57.207   -0.34        NaN
2018-04-03 13:59:34.636   -0.33        NaN
2018-04-03 14:00:34.565   -0.33        NaN
2018-04-03 14:01:19.994   -0.37        NaN
2018-04-03 14:02:29.636   -0.34        NaN
2018-04-03 14:03:31.599   -0.32        NaN
2018-04-03 14:04:30.779   -0.33        NaN
2018-04-03 14:05:31.733   -0.35        NaN
2018-04-03 14:06:33.290   -0.38        NaN
2018-04-03 14:07:37.459   -0.39        NaN
2018-04-03 14:08:36.361   -0.36        NaN
2018-04-03 14:09:36.577   -0.37       62.2
tehfink
fuente
¡Gracias! Me había acostumbrado a filtrar y luego fusionar DataFrames y Series 'así: df_larger_dataframe['values'] = df_filtered_dataframe['filtered_values'] y no ha funcionado últimamente en TimeSeries, ¡su código lo resolvió!
tw0000
2

Perdí un par de horas en el mismo problema. En mi caso, tuve que reiniciar_index () de un marco de datos antes de usar la función aplicar. Antes de fusionar o buscar desde otro conjunto de datos indexados, debe restablecer el índice ya que 1 conjunto de datos solo puede tener 1 índice.

rishi jain
fuente
2

Solución simple que funcionó para mí

Ejecutar df.reset_index(inplace=True)antes de agrupar.

Gracias a este comentario de github por la solución.

Connor
fuente
@Chris_vr elimine la parte in situ si desea que devuelva el marco de datos
Connor