2017-10-14 68 views
1

使用的SQLAlchemy我定義我自己TypeDecorator存儲大熊貓DataFrames在錄入數據庫的編碼爲JSON字符串。SQLAlchemy的TypeDecorators和比較錯誤

class db_JsonEncodedDataFrameWithTimezone(db.TypeDecorator): 
    impl = db.Text 

    def process_bind_param(self, value, dialect): 
     if value is not None and isinstance(value, pd.DataFrame): 
      timezone = value.index.tz.zone 
      df_json = value.to_json(orient="index") 
      data = {'timezone': timezone, 'df': df_json, 'index_name': value.index.name} 
      value = json.dumps(data) 
     return value 

    def process_result_value(self, value, dialect): 
     if value is not None: 
      data = json.loads(value) 
      df = pd.read_json(data['df'], orient="index") 
      df.index = df.index.tz_localize('UTC') 
      df.index = df.index.tz_convert(data['timezone']) 
      df.index.name = data['index_name'] 
      value = df 
     return value 

這適用於第一次數據庫保存,加載也很好。

問題是當我增加值,即改變數據幀,並嘗試改變數據庫。當我調用

db.session.add(entity) 
db.session.commit() 

我得到它指向比較值是該問題的回溯:

x == y 
ValueError: Can only compare identically-labeled DataFrame Objects. 

所以我懷疑我的問題有事情做與強迫比較。我曾嘗試三兩件事,都失敗了,我真的不知道下一步該怎麼做:

#1st failed solution attempt inserting 
coerce_to_is_types = (pd.DataFrame,) 

#2nd failed solution attempt inserting 
def coerce_compared_value(self, op, value): 
    return self.impl.coerce_compared_value(op, value) 

#3rd failed solution attempt 
class comparator_factory(db.Text.comparator_factory): 
    def __eq__(self, other): 
     try: 
      value = (self == other).all().all() 
     except ValueError: 
      value = False 
     return value 

回答

0

在我的第四次嘗試,我想我找到了答案,我直接創建,我插在我自己的比較功能Type類的上方。這樣可以避免在我的DataFrame上執行操作符'x == y':

def compare_values(self, x, y): 
    from pandas.util.testing import assert_frame_equal 
    try: 
     assert_frame_equal(x, y, check_names=True, check_like=True) 
     return True 
    except (AssertionError, ValueError, TypeError): 
     return False 

此性質的另一個問題後來出現在我的代碼中。解決的辦法是修改上述首先嚐試自然作比較,如果失敗則實現以上:

try: 
    value = x == y 
except: 
    # some other overwriting comparision method such as above