#python #pandas #digest
#python #pandas #дайджест
Вопрос:
Я хотел бы эффективно вычислить дайджест фрейма данных Pandas, который однозначно и воспроизводимо идентифицирует его содержимое (для целей управления версиями). Предположим, что на данный момент я не беспокоюсь о порядке следования, dtypes, типах индекса и столбцах. Также предположим, что и индекс, и столбцы уже отсортированы monotonic_increasing .
Со значениями все идет достаточно хорошо (опять же, для упрощения, предположим np.float64
). Но у меня возникли проблемы с индексом (и столбцами), и я не получаю согласованный дайджест. Конечно, я могу делать такие вещи, как преобразование индекса в строку, а затем байты utf-8, но это медленно.
Вот упрощенный пример:
import hashlib
def pd_val_sha1(df):
x = df.values
if not x.flags.c_contiguous:
x = x.copy(order='C')
return hashlib.sha1(x).hexdigest()
Тест:
import pandas as pd
import io
str = """s,e,id,x,y,z
2012-01-01,2013-01-01,b,NaN,2,3
2015-10-27,2015-11-03,a,0.04,12.7,NaN
2015-11-15,2016-01-01,a,7.3,-1.2,8
"""
df = pd.read_csv(io.StringIO(str), parse_dates=[0,1], index_col=[0,1,2]).sort_index()
df
Out:
x y z
s e id
2012-01-01 2013-01-01 b NaN 2.0 3.0
2015-10-27 2015-11-03 a 0.04 12.7 NaN
2015-11-15 2016-01-01 a 7.30 -1.2 8.0
SHA-1 значений:
pd_val_sha1(df)
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'
pd_val_sha1(df.head())
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'
pd_val_sha1(pd.concat([df.ix[0:2], df.ix[2:3]]))
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'
Пока все хорошо. Но когда дело доходит до индекса:
pd_val_sha1(df.index)
>>> inconsistent value (re-run the example from read_csv and we'll get
... a different result).
Я пробовал разные другие вещи, например, используя index.data
или index.to_native_types()
или np.array(index.tolist())
вместо index.values
, но я все равно получаю противоречивые результаты, поскольку я полагаю, что базовые данные могут отличаться.
Одна вещь, которая, кажется, работает до сих пор hashlib.sha1(np.array(df.index.format())).hexdigest()
. Но это медленно, например, 2 минуты 34 секунды для (5000000,12) фрейма данных, тогда как само содержимое отпечатывается за 900 мс.
Есть предложения?
Ответ №1:
Иногда решение находится прямо у нас под носом…
from sklearn.externals import joblib
%%time
joblib.hash(df, hash_name='sha1')
>>> consistent value that depends on values and axes
Wall time: 1.66 s (for the (5000000,12) DataFrame mentioned above)