Co oznacza „ValueError: nie można reindeksować ze zduplikowanej osi”?

254

Dostaję, ValueError: cannot reindex from a duplicate axisgdy próbuję ustawić indeks do określonej wartości. Próbowałem to odtworzyć na prostym przykładzie, ale nie mogłem tego zrobić.

Oto moja sesja wewnątrz ipdbśledzenia. Mam DataFrame z indeksem ciągów i kolumnami liczb całkowitych, wartościami zmiennoprzecinkowymi. Jednak gdy próbuję utworzyć sumindeks sumy wszystkich kolumn, pojawia się ValueError: cannot reindex from a duplicate axisbłąd. Stworzyłem małą ramkę DataFrame o tych samych cechach, ale nie byłem w stanie odtworzyć problemu, czego mógłbym brakować?

Naprawdę nie rozumiem, co to ValueError: cannot reindex from a duplicate axisznaczy, co oznacza ten komunikat o błędzie? Może to pomoże mi zdiagnozować problem, i to jest najbardziej odpowiedzialna część mojego pytania.

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

Oto błąd:

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

Próbowałem to odtworzyć na prostym przykładzie, ale mi się nie udało

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
źródło
1
Czy jest jakaś szansa, że ​​zaciemniłeś prawdziwe nazwy kolumn swojej macierzy powinowactwa? (tj. zastąpił rzeczywiste wartości czymś innym, aby ukryć poufne informacje)
Korem
@Korem, nie sądzę, że to prawda, ale nawet jeśli to prawda, dlaczego miałoby to powodować powyższy błąd?
Akavall,
2
Zwykle widzę to, gdy przypisany indeks ma zduplikowane wartości. Ponieważ w twoim przypadku przypisujesz wiersz, oczekiwałem duplikatu w nazwach kolumn. Dlatego spytałem.
Korem
@Korem, Rzeczywiście moje rzeczywiste dane miały zduplikowane wartości indeksu i byłem w stanie odtworzyć błąd w małym przykładzie, gdy obecne były zduplikowane wartości indeksu. W pełni odpowiedziałeś na moje pytanie. Dziękuję Ci. Czy masz coś przeciwko, by udzielić odpowiedzi?
Akavall,

Odpowiedzi:

170

Ten błąd zwykle pojawia się po dołączeniu / przypisaniu do kolumny, gdy indeks ma zduplikowane wartości. Ponieważ przypisujesz do wiersza, podejrzewam, że istnieje zduplikowana wartość w affinity_matrix.columns, być może nie pokazana w twoim pytaniu.

Korem
źródło
20
Aby być bardziej precyzyjnym, w moim przypadku była w nim zduplikowana wartość affinity_matrix.index, ale myślę, że to ta sama koncepcja.
Akavall,
24
Dla tych, którzy przyjdą do tego później, indexoznacza zarówno rowi column namesspędziłem 20 minut na indeksie wierszy, ale okazało się, że mam zduplikowane nazwy kolumn, które spowodowały ten błąd.
Jason Gol
Aby dodać do tego, napotkałem ten błąd, gdy próbowałem ponownie zindeksować ramkę danych na liście kolumn. Co dziwne, mój duplikat znajdował się w mojej oryginalnej ramce danych, więc sprawdź oba!
m8_
163

Jak powiedzieli inni, prawdopodobnie masz oryginalne wartości w oryginalnym indeksie. Aby je znaleźć:

df[df.index.duplicated()]

Mateusz
źródło
39
Aby usunąć wiersze ze zduplikowanymi indeksami, użyj:df = df[~df.index.duplicated()]
tuomastik
4
Dla DatetimeIndexdataframes ed można resampledo żądanej częstotliwości, a następnie podjąć .first(), .mean()itp
BallpointBen
28

Wskaźniki ze zduplikowanymi wartościami często powstają, jeśli utworzysz ramkę danych przez połączenie innych ramek danych. JEŻELI nie zależy Ci na zachowaniu wartości indeksu i chcesz, aby były one unikatowymi wartościami, po połączeniu danych ustaw ignore_index=True.

Alternatywnie, aby zastąpić bieżący indeks nowym, zamiast używać df.reindex(), ustaw:

df.index = new_index
Rebeku
źródło
8
Użyłem ignore_index = True, aby mój kod działał z połączonymi ramkami danych
Gabi Lee
Rzeczywiście, ignore_index=Falsejest domyślny; jeśli skorzystanie z tej opcji appendw ogóle zmieni zachowanie, będzie musiało tak być, ponieważ ustawiłeś ją na True.
Jeffrey Benjamin Brown
17

W przypadku osób, które nadal borykają się z tym błędem, może się to również zdarzyć, jeśli przypadkowo utworzysz zduplikowaną kolumnę o tej samej nazwie. Usuń zduplikowane kolumny w taki sposób:

df = df.loc[:,~df.columns.duplicated()]
Język wężowaty
źródło
12

Po prostu pomiń błąd, używając .valuesna końcu.

affinity_matrix.loc['sums'] = affinity_matrix.sum(axis=0).values
Hadij
źródło
To jest dokładnie to, co potrzebne! Próbuję utworzyć nową kolumnę, ale miałem indeks z duplikatami. Używanie .valueszrobiło lewę
Paul Wildenhain
8

Ten błąd napotkałem dzisiaj, gdy chciałem dodać nową kolumnę w ten sposób

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

Chciałem przetworzyć REMARKkolumnę df_tempzwracającą 1 lub 0. Jednak wpisałem niepoprawną zmienną za pomocą df. I zwrócił błąd w następujący sposób:

----> 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

Jak widać, właściwym kodem powinien być

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

Ponieważ dfi df_tempmają inną liczbę wierszy. Więc wróciło ValueError: cannot reindex from a duplicate axis.

Mam nadzieję, że to zrozumiesz, a moja odpowiedź może pomóc innym osobom w debugowaniu ich kodu.

Idąc moją drogą
źródło
4

W moim przypadku ten błąd pojawił się nie z powodu zduplikowanych wartości, ale dlatego, że próbowałem dołączyć krótszą serię do ramki danych: oba miały ten sam indeks, ale seria miała mniej wierszy (brak kilku pierwszych). Do moich celów zadziałały:

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
źródło
Dziękuję Ci! Przyzwyczaiłem się do filtrowania i późniejszego łączenia DataFrames i Series, i tak: df_larger_dataframe['values'] = df_filtered_dataframe['filtered_values'] ostatnio nie działało na TimeSeries - twój kod to rozwiązał!
tw0000
2

Zmarnowałem kilka godzin na ten sam problem. W moim przypadku musiałem zresetować ramkę danych przed użyciem funkcji wprowadzania. Przed scaleniem lub wyszukaniem z innego zindeksowanego zestawu danych należy zresetować indeks, ponieważ 1 zestaw danych może mieć tylko 1 indeks.

rishi jain
źródło
2

Prosta poprawka, która zadziałała dla mnie

Uruchom df.reset_index(inplace=True)przed zgrupowaniem.

Dziękuję za komentarz github dotyczący rozwiązania.

Connor
źródło
@Chris_vr usuń część wewnętrzną, jeśli chcesz, aby zwróciła ramkę danych
Connor