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

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.


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()]


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

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()]

12

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

affinity_matrix.loc['sums'] = affinity_matrix.sum(axis=0).values

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.


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

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.


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.


@Chris_vr usuń część wewnętrzną, jeśli chcesz, aby zwróciła ramkę danych
— Connor
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.