O que significa `ValueError: não é possível reindexar a partir de um eixo duplicado`?

254

Estou recebendo um ValueError: cannot reindex from a duplicate axisquando estou tentando definir um índice para um determinado valor. Tentei reproduzir isso com um exemplo simples, mas não consegui.

Aqui está a minha sessão dentro do ipdbrastreamento. Eu tenho um DataFrame com índice de seqüência de caracteres e colunas inteiras, valores flutuantes. No entanto, quando tento criar sumíndice para a soma de todas as colunas, estou recebendo ValueError: cannot reindex from a duplicate axiserro. Criei um pequeno DataFrame com as mesmas características, mas não consegui reproduzir o problema. O que poderia estar faltando?

Realmente não entendo o que ValueError: cannot reindex from a duplicate axissignifica, o que significa essa mensagem de erro? Talvez isso me ajude a diagnosticar o problema, e essa é a parte mais responsável da minha pergunta.

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

Aqui está o erro:

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

Tentei reproduzir isso com um exemplo simples, mas falhei

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
fonte
1
Existe alguma chance de você ofuscar os nomes reais das colunas da sua matriz de afinidade? (ou seja, substituiu os valores reais com outra coisa para esconder informações sensíveis)
Korem
@ Korem, eu não acho que isso seja verdade, mas mesmo se isso for verdade, por que isso causaria o erro acima?
Akavall
2
Normalmente, vejo isso quando o índice atribuído a tem valores duplicados. Como você está atribuindo uma linha no seu caso, eu esperava uma duplicata nos nomes das colunas. É por isso que eu pedi.
Korem
@ Korem, Na verdade, meus dados reais tinham valores duplicados de índice, e eu pude reproduzir o erro no pequeno exemplo quando estavam presentes valores duplicados de índice. Você respondeu totalmente a minha pergunta. Obrigado. Você se importa de colocá-lo como resposta?
Akavall

Respostas:

170

Esse erro geralmente ocorre quando você ingressa / atribui a uma coluna quando o índice tem valores duplicados. Como você está atribuindo uma linha, suspeito que exista um valor duplicado affinity_matrix.columns, talvez não mostrado na sua pergunta.

Korem
fonte
20
Para ser mais preciso, no meu caso, havia um valor duplicado affinity_matrix.index, mas acho que esse é o mesmo conceito.
precisa saber é o seguinte
24
Para quem chega mais tarde, indexsignifica ambos rowe column names, passou 20 minutos no índice de linhas, mas acabou obtendo nomes de colunas duplicados que causaram esse erro.
Jason Goal
Para adicionar isso, me deparei com esse erro ao tentar reindexar um quadro de dados em uma lista de colunas. Curiosamente, minha duplicata estava no meu quadro de dados original, portanto, verifique as duas!
M8_ 06/11/19
163

Como já foi dito, você provavelmente tem valores duplicados no seu índice original. Para encontrá-los, faça o seguinte:

df[df.index.duplicated()]

Mateus
fonte
39
Para remover linhas com índices duplicados, use:df = df[~df.index.duplicated()]
tuomastik 31/03
4
Para DatetimeIndexdataframes ed, você pode resamplea frequência desejada e depois tomar .first(), .mean()etc.
BallpointBen
28

Os índices com valores duplicados geralmente surgem se você criar um DataFrame concatenando outros DataFrames. Se você não se preocupa em preservar os valores do seu índice e deseja que eles sejam valores únicos, quando concatenar os dados, defina ignore_index=True.

Como alternativa, para substituir o índice atual por um novo, em vez de usar df.reindex(), defina:

df.index = new_index
Rebeku
fonte
8
Eu costumava ignore_index = True para obter o meu código para trabalhar com dataframes concatenadas
Gabi Lee
De fato, ignore_index=Falseé o padrão; se o uso da opção for alterar appendo comportamento de alguma forma, será necessário que você a configure True.
Jeffrey Benjamin Brown
17

Para pessoas que ainda estão lutando com esse erro, isso também pode acontecer se você criar acidentalmente uma coluna duplicada com o mesmo nome. Remova colunas duplicadas da seguinte forma:

df = df.loc[:,~df.columns.duplicated()]
Parseltongue
fonte
12

Basta pular o erro usando .valuesno final.

affinity_matrix.loc['sums'] = affinity_matrix.sum(axis=0).values
Hadij
fonte
Isso é exatamente o que eu precisava! Apenas tentando criar uma nova coluna, mas eu tinha um índice com duplicatas. Usando .valuesfez o truque
Paul Wildenhain 02/01
8

Encontrei este erro hoje quando quis adicionar uma nova coluna como esta

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

Eu queria processar a REMARKcoluna de df_temppara retornar 1 ou 0. No entanto, digitei a variável errada com df. E retornou um erro 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 você pode ver, o código certo deve ser

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

Porque dfe df_temptem um número diferente de linhas. Então voltou ValueError: cannot reindex from a duplicate axis.

Espero que você possa entender e minha resposta possa ajudar outras pessoas a depurar seu código.

Indo à minha maneira
fonte
4

No meu caso, esse erro apareceu não por causa de valores duplicados, mas porque tentei associar uma série mais curta a um Dataframe: ambos tinham o mesmo índice, mas a série tinha menos linhas (faltando as primeiras). O seguinte funcionou para meus 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
fonte
Obrigado! Eu me acostumei a filtrar e depois mesclar DataFrames e Series 'da seguinte maneira: df_larger_dataframe['values'] = df_filtered_dataframe['filtered_values'] e não tem funcionado ultimamente no TimeSeries - seu código o resolveu!
tw0000 26/06
2

Perdi duas horas no mesmo assunto. No meu caso, tive que reset_index () de um quadro de dados antes de usar a função aplicar. Antes de mesclar ou procurar em outro conjunto de dados indexado, é necessário redefinir o índice, pois 1 conjunto de dados pode ter apenas 1 Índice.

rishi jain
fonte
2

Correção simples que funcionou para mim

Execute df.reset_index(inplace=True)antes do agrupamento.

Obrigado a este comentário do github pela solução.

Connor
fonte
@Chris_vr remova a parte interna, se desejar que ela retorne o dataframe
Connor