2015-03-27 16 views
7

Để xác nhận rằng tôi hiểu những gì Pandas df.groupby()df.reset_index() làm, tôi đã cố gắng để làm một chuyến đi vòng quanh từ một dataframe lên một phiên bản nhóm của cùng một dữ liệu và ngược lại. Sau khi chuyến đi khứ hồi, các cột và hàng phải được sắp xếp lại, vì groupby() ảnh hưởng đến thứ tự hàng và reset_index() ảnh hưởng đến thứ tự cột, nhưng sau hai thao tác nhanh chóng để đưa các cột và chỉ mục trở lại theo thứ tự, các khung dữ liệu trông giống hệt nhau:Làm thế nào Pandas DataFrames có thể xuất hiện giống hệt nhau nhưng không bằng()?

  • Cùng một danh sách tên cột.
  • Cùng một loại dtypes cho mỗi cột.
  • Giá trị chỉ số tương ứng hoàn toàn bằng nhau.
  • Giá trị dữ liệu tương ứng hoàn toàn bằng nhau.

Tuy nhiên, sau khi tất cả các kiểm tra này thành công, df1.equals(df5) trả lại giá trị đáng kinh ngạc False.

Sự khác biệt giữa các khung dữ liệu này là equals() phát hiện ra rằng tôi chưa tìm ra cách tự kiểm tra? đang

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

Kết quả mà tôi nhận được khi tôi chạy kịch bản là:

    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 

Nhờ sự giúp đỡ!

+0

Một cách khác để kiểm tra là để sử dụng 'pandas.util.testing.assert_frame_equal'. Điều đó có thể cung cấp cho bạn một báo cáo về những gì Pandas nghĩ là khác nhau. – jiffyclub

+0

Ý tưởng hay! Chỉ cần thử nó. Nó không đặt ngoại lệ nếu các đối số của nó là 'assert_frame_equal (df1, df5)' làm dòng cuối cùng trong kịch bản trên. Vì vậy, có vẻ như họ nghĩ rằng họ bằng nhau mặc dù '.equals()' không? –

Trả lời

5

này cảm thấy như một lỗi với tôi, nhưng có thể chỉ đơn giản là tôi đang hiểu lầm gì đó. Các khối được liệt kê theo một thứ tự khác nhau:

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

Trong core/internals.py, chúng tôi có phương pháp 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)) 

và cuối cùng all giả định rằng các khối trong selfother tương ứng. Nhưng nếu chúng ta thêm một số print cuộc gọi trước đó, chúng ta thấy:

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

và vì vậy chúng tôi đang so sánh những điều sai trái. Lý do tôi không chắc chắn hay không đây là một lỗi là vì tôi không chắc liệu equalsnghĩa được điều này khó tính hay không. Nếu vậy, tôi nghĩ rằng có một lỗi doc, ít nhất, bởi vì equals sau đó nên hét lên rằng nó không có nghĩa là để được sử dụng cho những gì bạn có thể nghĩ rằng nó sẽ được từ tên và docstring.

+0

Bạn có thể gây ra vấn đề này không? – joris

+0

ban đầu được báo cáo ở đây: https://github.com/pydata/pandas/issues/9330; khối đặt hàng là một chi tiết impl atm. có một số tùy chọn khi anh ấy kết thúc vấn đề để làm cho điều này phù hợp. – Jeff

+0

Cảm ơn tất cả! Tôi đã thêm mã mẫu này vào vấn đề này để cảnh báo họ rằng đây không phải là HDF cụ thể nhưng có thể tấn công bất kỳ ai. –

Các vấn đề liên quan