2015-03-27 24 views
7

Pandalar df.groupby() ve df.reset_index()'un ne yaptığını anladığımı doğrulamak için, bir veri çerçevesinden aynı verinin gruplandırılmış sürümüne ve geri dönüşe gidiş gelişini denedim. gidiş-dönüş sonra sütunlar ve satırlar groupby() Satır sırasını etkiler ve reset_index() sütun sırasını etkiler, ama geri sırayla sütunları ve dizini koymak için iki hızlı manevralar sonrasında dataframes özdeş bakmak çünkü, tekrar sıralanabilir zorunda:Pandas DataFrames nasıl aynı görünebilir, ancak eşittir()?

  • Aynı sütun adları listesi.
  • Her sütun için aynı parçacıklar.
  • Karşılık gelen dizin değerleri kesinlikle eşittir.
  • İlgili veri değerleri kesinlikle eşittir. Tüm bu denetimlerden başarılı sonra

Ancak, df1.equals(df5) şaşırtıcı değerini False döndürür.

Bu veri çerçeveleri arasındaki fark, kendimi nasıl kontrol edeceğimi henüz çözmediğimi ortaya çıkaran equals()?

Testi kodu:

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

Ben script çalıştırdığınızda aldığım çıktı: Herhangi bir yardım için

    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 

Teşekkür!

+0

Diğer bir yöntem ise 'pandas.util.testing.assert_frame_equal' kullanmaktır. Bu, Panda'ların farklı olduğunu düşündüğü hakkında bir rapor verebilir. – jiffyclub

+0

İyi fikir! Sadece denedim. Yukarıdaki betikteki son satırın argümanları "assert_frame_equal (df1, df5)" ise istisna oluşturmaz. Yani eşittir diye düşünmek bile onların 'eşit değil() 'değil mi? –

cevap

5

Bu benim için bir hata gibi görünüyor, ancak basitçe bir şeyi yanlış anladığım olabilir. bloklar farklı bir sırada listelenmiştir:

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

core/internals.py, biz BlockManager yöntemini

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

sahip ve son all varsayar self ve other tekabül ettiği blokları.

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

ve bu yüzden yanlış şeyler kıyaslıyorsun: bunun önce bazı print çağrıları eklerseniz Ama biz görüyoruz. Bunun bir hata olup olmadığından emin olmamamın nedeni, equals'un 'un anlamına gelip gelmediğinden emin değilim. Eğer öyleyse, sanırım bir doktor hatası var, en azından, equals, bunun adından ve dokunduğundan olabileceğini düşündüğünüz şeylerin kullanılması için kullanılmaması gerektiğini belirtmelidir.

+0

Bunun için bir sorun olur mu? – joris

+0

başlangıçta burada bildirilmiştir: https://github.com/pydata/pandas/issues/9330; blok siparişi bir detay ayrıntısıdır atm. Bu tutarlı hale getirmek için konunun sonunda bazı seçenekler var. – Jeff

+0

Teşekkürler, hepinize! Bu örnek kodun, HDF'ye özgü olmadığını, ancak herkese vurabileceği konusunda uyarmak için konuya ekledim. –