2015-03-27 7 views
7

Per confermare di aver capito cosa fanno i panda df.groupby() e , ho tentato di fare un viaggio di andata e ritorno da un dataframe a una versione raggruppata degli stessi dati e viceversa. Dopo l'andata e ritorno delle colonne e righe dovevano essere separate nuovo, perché groupby() affetti ordine riga e reset_index() affetti ordine della colonna, ma dopo due manovre rapide per mettere le colonne e indice in ordine, i dataframes aspetto identico:In che modo Pandas DataFrames può apparire identico ma fail equals()?

  • Stesso elenco di nomi di colonne.
  • Stessi tipi per ogni colonna.
  • I valori di indice corrispondenti sono rigorosamente uguali.
  • I valori dei dati corrispondenti sono strettamente uguali.

Tuttavia, al termine di tutti questi controlli, df1.equals(df5) restituisce il valore sbalorditivo False.

Che differenza tra questi dati è equals() che si scopre che non ho ancora capito come controllare da solo? Codice

prova:

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

L'uscita che ricevo quando faccio funzionare lo scritto è:

    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 

Grazie per qualsiasi aiuto!

+0

Un altro modo per controllare è usare 'pandas.util.testing.assert_frame_equal'. Questo potrebbe darti un rapporto su cosa pensa Panda sia diverso. – jiffyclub

+0

Buona idea! Ho appena provato. Non solleva eccezioni se i suoi argomenti sono 'assert_frame_equal (df1, df5)' come ultima riga nello script sopra. Quindi sembra che siano uguali anche se '.equals()' no? –

risposta

5

Questo mi sembra un insetto, ma potrebbe essere semplicemente che sto fraintendendo qualcosa. I blocchi sono elencati in ordine diverso:

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

In core/internals.py, abbiamo il metodo 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)) 

e quell'ultimo all presuppone che i blocchi in self e other corrispondono. Ma se si aggiungono alcuni print chiamate prima di esso, vediamo:

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

e quindi stiamo confrontando le cose sbagliate. Il motivo per cui non sono sicuro se questo sia o meno un bug è perché non sono sicuro se equals sia significasse essere pignolo o no. Se è così, penso che ci sia un problema con i doc, almeno, perché equals dovrebbe quindi gridare che non è destinato a essere usato per quello che si potrebbe pensare sarebbe dal nome e dalla docstring.

+0

Puoi fare un problema per questo? – joris

+0

è stato originariamente riportato qui: https://github.com/pydata/pandas/issues/9330; l'ordine dei blocchi è un dettaglio impl a. ci sono alcune opzioni alla fine del problema per renderlo coerente. – Jeff

+0

Grazie a tutti! Ho aggiunto questo codice di esempio al problema per avvertirli che questo non è specifico dell'HDF, ma può colpire chiunque. –

Problemi correlati