2015-03-27 4 views
7

Aby potwierdzić, że rozumiem, co robią Pandy df.groupby() i df.reset_index(), próbowałem wykonać obieg z ramki danych do zgrupowanej wersji tych samych danych iz powrotem. Po w obie kolumny i wiersze musiały być ponownie sortowane, bo groupby() wpływa na kolejność wierszy i reset_index() wpływa na kolejność kolumn, ale po dwóch szybkich manewrów, aby umieścić kolumny i indeks z powrotem w porządku, dataframes wyglądają identycznie:W jaki sposób Pandas DataFrames może wyglądać identycznie, ale kończy się niepowodzeniem()?

  • Ta sama lista nazw kolumn.
  • Te same dtypes dla każdej kolumny.
  • Odpowiednie wartości indeksu są ściśle równe.
  • Odpowiednie wartości danych są ściśle równe.

Jednak po pomyślnym zakończeniu wszystkich tych testów df1.equals(df5) zwraca zdumiewającą wartość False.

Jaka jest różnica między tymi ramkami danych: equals() ujawniając, że jeszcze nie wymyśliłem, jak sprawdzić samemu? Kod

Test:

csv_text = """\ 
Title,Year,Director 
North by Northwest,1959,Alfred Hitchcock 
Notorious,1946,Alfred Hitchcock 
The Philadelphia Story,1940,George Cukor 
To Catch a Thief,1955,Alfred Hitchcock 
His Girl Friday,1940,Howard Hawks 
""" 

import pandas as pd 

df1 = pd.read_csv('sample.csv') 
df1.columns = map(str.lower, df1.columns) 
print(df1) 

df2 = df1.groupby(['director', df1.index]).first() 
df3 = df2.reset_index('director') 
df4 = df3[['title', 'year', 'director']] 
df5 = df4.sort_index() 
print(df5) 

print() 
print(repr(df1.columns)) 
print(repr(df5.columns)) 
print() 
print(df1.dtypes) 
print(df5.dtypes) 
print() 
print(df1 == df5) 
print() 
print(df1.index == df5.index) 
print() 
print(df1.equals(df5)) 

Wyjście że otrzymam gdy uruchamiam skrypt jest:

    title year   director 
0  North by Northwest 1959 Alfred Hitchcock 
1    Notorious 1946 Alfred Hitchcock 
2 The Philadelphia Story 1940  George Cukor 
3  To Catch a Thief 1955 Alfred Hitchcock 
4   His Girl Friday 1940  Howard Hawks 
        title year   director 
0  North by Northwest 1959 Alfred Hitchcock 
1    Notorious 1946 Alfred Hitchcock 
2 The Philadelphia Story 1940  George Cukor 
3  To Catch a Thief 1955 Alfred Hitchcock 
4   His Girl Friday 1940  Howard Hawks 

Index(['title', 'year', 'director'], dtype='object') 
Index(['title', 'year', 'director'], dtype='object') 

title  object 
year   int64 
director object 
dtype: object 
title  object 
year   int64 
director object 
dtype: object 

    title year director 
0 True True  True 
1 True True  True 
2 True True  True 
3 True True  True 
4 True True  True 

[ True True True True True] 

False 

dzięki za pomoc!

+0

Innym sposobem sprawdzenia jest użycie 'pandas.util.testing.assert_frame_equal'. To może dać ci raport o tym, co myśli Panda jest inna. – jiffyclub

+0

Dobry pomysł! Wypróbowałem to. Nie wywołuje żadnego wyjątku, jeśli jego argumenty to "assert_frame_equal (df1, df5)" jako ostatnia linia w powyższym skrypcie. Wydaje się więc, że są one równe, chociaż '.equals()' nie działa? –

Odpowiedz

5

To wydaje się być dla mnie błędem, ale może być po prostu tym, że coś nie rozumiem. Bloki te są wymienione w dowolnej kolejności:

>>> df1._data 
BlockManager 
Items: Index(['title', 'year', 'director'], dtype='object') 
Axis 1: Int64Index([0, 1, 2, 3, 4], dtype='int64') 
IntBlock: slice(1, 2, 1), 1 x 5, dtype: int64 
ObjectBlock: slice(0, 4, 2), 2 x 5, dtype: object 
>>> df5._data 
BlockManager 
Items: Index(['title', 'year', 'director'], dtype='object') 
Axis 1: Int64Index([0, 1, 2, 3, 4], dtype='int64') 
ObjectBlock: slice(0, 4, 2), 2 x 5, dtype: object 
IntBlock: slice(1, 2, 1), 1 x 5, dtype: int64 

W core/internals.py mamy SPOSÓB BlockManager

def equals(self, other): 
    self_axes, other_axes = self.axes, other.axes 
    if len(self_axes) != len(other_axes): 
     return False 
    if not all (ax1.equals(ax2) for ax1, ax2 in zip(self_axes, other_axes)): 
     return False 
    self._consolidate_inplace() 
    other._consolidate_inplace() 
    return all(block.equals(oblock) for block, oblock in 
       zip(self.blocks, other.blocks)) 

i ostatni all zakłada się, że bloki self i other odpowiadają. Ale jeśli dodamy kilka print połączeń przed nim, widzimy:

>>> df1.equals(df5) 
blocks self: (IntBlock: slice(1, 2, 1), 1 x 5, dtype: int64, ObjectBlock: slice(0, 4, 2), 2 x 5, dtype: object) 
blocks other: (ObjectBlock: slice(0, 4, 2), 2 x 5, dtype: object, IntBlock: slice(1, 2, 1), 1 x 5, dtype: int64) 
False 

a więc mamy porównanie złe rzeczy. Powód, dla którego nie jestem pewien, czy jest to błąd, jest taki, że nie jestem pewien, czy jest on tak zwinny czy nie. Jeśli tak, to myślę, że przynajmniej istnieje błąd związany z dokumentem, ponieważ wtedy equals powinien krzyczeć, że nie jest przeznaczony do użycia z tego, co mogłoby się wydawać, że pochodzi od nazwy i docstrukcji.

+0

Czy możesz naruszyć ten problem? – joris

+0

został zgłoszony tutaj: https://github.com/pydata/pandas/issues/9330; zamawianie bloków to detal imp end. jest kilka opcji na końcu tego wydania, aby było to spójne. – Jeff

+0

Dziękuję wszystkim! Dołączyłem ten przykładowy kod do ostrzeżenia, że ​​nie jest to zależne od HDF, ale może uderzyć w każdego. –

Powiązane problemy