2015-07-22 30 views
11

Mục tiêu của tôi là nhận giá trị băm duy nhất cho một DataFrame. Tôi lấy nó ra khỏi tập tin .csv. Toàn bộ điểm là nhận được cùng một băm mỗi lần tôi gọi hàm băm() trên đó.Nhận giá trị băm giống nhau cho một khung dữ liệu Pandas mỗi lần

Ý tưởng của tôi là tôi tạo ra các chức năng

def _get_array_hash(arr): 
    arr_hashable = arr.values 
    arr_hashable.flags.writeable = False 
    hash_ = hash(arr_hashable.data) 
    return hash_ 

được gọi mảng NumPy cơ bản, đặt nó vào trạng thái bất biến và nhận được băm của bộ đệm.

UPD INLINE.

Kể từ ngày 8 tháng 11 năm 2016, phiên bản này của chức năng không hoạt động nữa. Thay vào đó, bạn nên sử dụng

hash(df.values.tobytes()) 

Xem nhận xét cho Most efficient property to hash for numpy array.

END OF UPD INLINE.

Nó hoạt động cho mảng gấu trúc thường xuyên:

In [12]: data = pd.DataFrame({'A': [0], 'B': [1]}) 

In [13]: _get_array_hash(data) 
Out[13]: -5522125492475424165 

In [14]: _get_array_hash(data) 
Out[14]: -5522125492475424165 

Nhưng sau đó tôi cố gắng để áp dụng nó vào DataFrame thu được từ một tập tin .csv:

In [15]: fpath = 'foo/bar.csv' 

In [16]: data_from_file = pd.read_csv(fpath) 

In [17]: _get_array_hash(data_from_file) 
Out[17]: 6997017925422497085 

In [18]: _get_array_hash(data_from_file) 
Out[18]: -7524466731745902730 

Ai đó có thể giải thích cho tôi, làm thế nào là có thể ?

tôi có thể tạo DataFrame mới ra khỏi nó, như

new_data = pd.DataFrame(data=data_from_file.values, 
      columns=data_from_file.columns, 
      index=data_from_file.index) 

và nó hoạt động một lần nữa

In [25]: _get_array_hash(new_data) 
Out[25]: -3546154109803008241 

In [26]: _get_array_hash(new_data) 
Out[26]: -3546154109803008241 

Nhưng mục tiêu của tôi là để bảo tồn giá trị băm tương tự cho một dataframe qua ứng dụng khởi động theo thứ tự để lấy một số giá trị từ bộ nhớ cache.

+1

Điều này có thể giúp: https://github.com/TomAugspurger/engarde/issues/3 –

+0

Tôi đã thử cách tiếp cận với nhận giá trị băm của chỉ mục và cột và giá trị str (data_frame). Nó chậm và bị các vấn đề tương tự. – mkurnikov

+0

Tôi cũng quan tâm đến việc này - tôi có thể hỏi tại sao bạn đưa vào "arr_hashable.flags.writeable = False" không? Bạn có mong đợi hàm băm() có thể sửa đổi mảng không? –

Trả lời

4

Tôi đã gặp sự cố tương tự: kiểm tra xem liệu một khung dữ liệu có thay đổi không và tôi đã giải quyết nó bằng cách băm chuỗi serialization msgpack. Điều này có vẻ ổn định giữa các tải lại cùng một dữ liệu.

import pandas as pd 
import hashlib 
DATA_FILE = 'data.json' 

data1 = pd.read_json(DATA_FILE) 
data2 = pd.read_json(DATA_FILE) 

assert hashlib.md5(data1.to_msgpack()).hexdigest() == hashlib.md5(data2.to_msgpack()).hexdigest() 
assert hashlib.md5(data1.values.tobytes()).hexdigest() != hashlib.md5(data2.values.tobytes()).hexdigest() 
+0

Tôi tìm thấy '.to_msgpack()' ổn định trong Python 3.6 nhưng không phải trong 3.5 (không chắc chắn lý do tại sao, có thể có một cái gì đó để làm với từ điển được đặt hàng trong Python 3,6+). Chỉ cần giữ nó đơn giản và để '.to_csv(). Mã hóa ('utf-8')' thay thế. – ostrokach

1

Tính đến Pandas 0.20.1, bạn có thể sử dụng ít được biết đến (và kém tài liệu) hash_pandas_object (source code) đó là thời gian gần đây made public trong pandas.utils. Nó trả về một giá trị băm cho hàng tầm ảnh hưởng của dataframe (và hoạt động trên hàng loạt vv quá)

import pandas as pd 
import numpy as np 

np.random.seed(42) 
arr = np.random.choice(['foo', 'bar', 42], size=(3,4)) 
df = pd.DataFrame(arr) 

print(df) 
#  0 1 2 3 
# 0 42 foo 42 42 
# 1 foo foo 42 bar 
# 2 42 42 42 42 


from pandas.util import hash_pandas_object 
h = hash_pandas_object(df) 

print(h) 
# 0  5559921529589760079 
# 1 16825627446701693880 
# 2  7171023939017372657 
# dtype: uint64 

Bạn luôn có thể làm hash_pandas_object(df).sum() nếu bạn muốn một băm tổng thể của tất cả các hàng.

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