Python數據整合與數據准備-BigGorilla實例應用


  參考文檔:http://www.biggorilla.org/walkt/

  一、BigGorilla應用主要步驟

    如下圖:

    

  二、實例應用

    1、數據獲取

      urllib是非常受歡迎的用於在網絡上讀取數據的Python軟件包。在本部分中,我們使用urllib下載本教程所需的數據集。

      “Kaggle 5000 Movie Dataset”下載 所需的數據集是一個.csv文件,擁有以下代碼片段中指定的url。

    

 

  

    2、數據抽取

      “Kaggle 5000 Movie Dataset”存儲在.csv文件中,該文件已經完成結構化並且可供使用。另一方面,“IMDB Plain Text Data”是一系列需要進行處理以抽取數據的半結構化文本文件。快速查看每個文件的前幾行可以發現,每個文件都有不同的格式,

    並且必須單獨加以處理。

 

    3、數據歸檔和清理

      在此數據准備階段中的高級目標就是審視我們目前已經獲取和抽取的數據。這樣可以幫助我們熟悉數據,了解數據需要以什么方式進行清理或轉換,最終讓我們為數據整合任務的以下步驟准備數據。

      a、處理重復(清理)

        # 使用簡單的重復處理方法,即僅保留第一次出現的重復條目並移除剩余的重復條目

        
      
     b、
文本標准化(清理)
        
        我們將用來整合電影數據集的關鍵屬性是電影片名。因此,對這些片名進行標准化非常重要。以下代碼片段使所有電影片名變為小寫,然后移除某些字符,例如“’”和“?”,並替換一些其他特殊字符(例如“&”被替換為“and”)。
        
        

        

    4、數據匹配和合並

      使用Magellan進行數據匹配

      a、尋找一個候選集(攔截)

      本步驟的目標是使用簡單的啟發式規則限制我們認為是潛在匹配的配對數量。對於此任務,我們可以在各個數據集中新建一列,將重要屬性的值合並到單個字符串(我們稱之為混合)。然后,我們可以像之前一樣使用字符串類似項合並,

    尋找重要列的數值有一些重疊的條目組合。在此之前,我們需要將作為混合的一部分的列轉換為字符串。使用py_stringsimjoin程序包,我們可以輕松完成這些工作。

      

      現在,我們可以使用混合列創建所需的候選集(我們稱之為C)。

      b、指定要素

      下一步就是指定在py_entitymatching程序包中哪些列對應於各個數據幀中的要素。此外,我們需要指定哪些列對應於候選集中兩個數據幀中的外部要素。

      

      c、攔截工具故障排除

      

      d、從候選集采樣,label列

      

 

      e、機器學習算法訓練

      

       

      

      f、評估匹配質量

      

      g、使用訓練的模型匹配數據集

      

          

    三、完整代碼

    

#coding=utf8
#公共方法

class CommonM:

    # @classmethod
    @staticmethod
    def preprocess_title(title):
        '''字符串特殊字符處理'''
        title = title.lower()
        title = title.replace(',', ' ')
        title = title.replace("'", '')
        title = title.replace('&', 'and')
        title = title.replace('?', '')
        title = title.decode('utf-8', 'ignore')
        return title.strip()

############################################################
#coding=utf8
#數據獲取

# Importing urlib
import urllib
import os
import gzip


class acquireData:
    '''該類主要是獲取各種類型的文件'''

    def __init__(self):
        pass

    def down_csv_data(self):
        '''獲取csv文件'''
        # Creating the data folder
        if not os.path.exists('./data'):
            os.makedirs('./data')

        # Obtaining the dataset using the url that hosts it
        kaggle_url = 'https://github.com/sundeepblue/movie_rating_prediction/raw/master/movie_metadata.csv'
        if not os.path.exists('./data/kaggle_dataset.csv'):  # avoid downloading if the file exists
            response = urllib.urlretrieve(kaggle_url, './data/kaggle_dataset.csv')

        imdb_url = 'https://anaconda.org/BigGorilla/datasets/1/download/imdb_dataset.csv'
        if not os.path.exists('./data/imdb_dataset.csv'):  # avoid downloading if the file exists
            response = urllib.urlretrieve(imdb_url, './data/imdb_dataset.csv')


    def get_gz_data(self):
        '''獲取gz數據
        IMDB Plain Text Data(參見此處)是一系列文件,其中每個文件描述電影的一個或多個屬性。我們將重點關注電影屬性的子集,它表示我們僅對以下所列文件中的數個文件感興趣:
        genres.list.gz
        ratings.list.gz
        ** 注意: 上述文件的總大小約為30M。 運行以下代碼可能需要幾分鍾時間。
        '''

        # Obtaining IMDB's text files
        imdb_url_prefix = 'ftp://ftp.funet.fi/pub/mirrors/ftp.imdb.com/pub/'
        imdb_files_list = ['genres.list.gz', 'ratings.list.gz']
        # imdb_files_list = ['genres.list.gz']
        for name in imdb_files_list:
            if not os.path.exists('./data/' + name):
                response = urllib.urlretrieve(imdb_url_prefix + name, './data/' + name)
                urllib.urlcleanup()  # urllib fails to download two files from a ftp source. This fixes the bug!
                with gzip.open('./data/' + name) as comp_file, open('./data/' + name[:-3], 'w') as reg_file:
                    file_content = comp_file.read()
                    reg_file.write(file_content)

# obj = acquireData()
# obj.down_csv_data()
###################################################################################################

#coding=utf8
#數據匹配和合並

import os
import datetime
import time
import re
import csv
import pandas as pd
from os import walk
import urllib
import py_stringsimjoin as ssj
import py_stringmatching as sm

from pandas.core.frame import DataFrame
from extract_clean import extract_clean_data
import py_entitymatching as em
import LogFile

class match_merge_data:
    def __init__(self):
        pass

    def WriteToCsv(self, titls, data,filename='./data/finalResult-Magellan.csv'):

        # csvfile = os.path.join(os.getcwd(), 'csvtest.csv')
        with open(filename, 'wb') as f:
            writer = csv.writer(f)
            # 標題
            writer.writerow(titls)
            for item in data:
                # 內容
                writer.writerow(item)

    def match_merge_list(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        genreslist = obj.extract_genreslist()
        ratinglist = obj.extract_ratinglist()
        print ratinglist.shape[0]
        print genreslist.shape[0]
        brief_imdb_data = pd.merge(ratinglist, genreslist, how='inner', on=['norm_movie', 'year'])
        brief_imdb_data.head()
        print brief_imdb_data.shape[0]


    def match_merge_Kaggle_IMDB(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()
        # print kaggle_data.shape[0] #4919
        # print imdb_data.shape[0] #869178
        # 方法1
        data_attempt1 = pd.merge(imdb_data, kaggle_data, how='inner', left_on=['norm_title', 'norm_year'],
                                 right_on=['norm_movie_title', 'norm_title_year'])
        # print data_attempt1.shape[0] #4261
        data_attempt1.to_csv('./data/finalResult-IMDB.csv')


    def match_merge_Kaggle_IMDB_stringsimjoin(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()

        # 方法2
        imdb_data['id'] = range(imdb_data.shape[0])
        kaggle_data['id'] = range(kaggle_data.shape[0])
        #使用編輯距離度量來連接兩個表。從左表和右表找到元組,使編輯連接屬性之間的距離滿足輸入條件閾
        #。 例如,如果比較運算符是'<=',則找到元組對,其編碼距離是字符串之間的值連接屬性小於或等於輸入閾值,as在“閾值”中指定。
        similar_titles = ssj.edit_distance_join(imdb_data, kaggle_data, 'id', 'id', 'norm_title',
                                                'norm_movie_title', l_out_attrs=['title','norm_title', 'norm_year'],
                                                r_out_attrs=['movie_title','norm_movie_title', 'norm_title_year'], threshold=1)
        # selecting the entries that have the same production year
        data_attempt2 = similar_titles[similar_titles.r_norm_title_year == similar_titles.l_norm_year]
        data_attempt2.to_csv('./data/finalResult-stringsimjoin.csv')
        # data_attempt2.to_csv('./data/finalResult-stringsimjoin.csv', encoding='utf-8')
        # print data_attempt2.shape[0]#4696
        # print data_attempt3.shape[0]  # 10525

    def match_merge_Kaggle_IMDB_Magellan(self):
        # print str(datetime.datetime.now())[0:19]
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()

        imdb_data['id'] = range(imdb_data.shape[0])
        kaggle_data['id'] = range(kaggle_data.shape[0])

        # 方法3
        # 子步驟A: 尋找一個候選集(攔截)
        # repeating the same thing for the Kaggle dataset
        ssj.dataframe_column_to_str(kaggle_data, 'budget', inplace=True)
        kaggle_data['mixture'] = kaggle_data['norm_movie_title'] + ' ' + kaggle_data['norm_title_year'] + kaggle_data['budget']

        # transforming the "budget" column into string and creating a new **mixture** column
        ssj.dataframe_column_to_str(imdb_data, 'budget', inplace=True)
        imdb_data['mixture'] = imdb_data['norm_title'] + ' ' +          imdb_data['norm_year'] + ' ' +    imdb_data['budget']

        #使用重疊系數連接兩個表。
        C = ssj.overlap_coefficient_join(kaggle_data, imdb_data, 'id', 'id', 'mixture', 'mixture',
                                         sm.WhitespaceTokenizer(),
                                         l_out_attrs=['movie_title','norm_movie_title', 'norm_title_year', 'duration',
                                                      'budget', 'content_rating'],
                                         r_out_attrs=['title','norm_title', 'norm_year', 'length', 'budget', 'mpaa'],
                                         threshold=0.65)
        # C.shape()
        rowCount = C.shape[0] #34
        # print C.shape[0]

        # 子步驟B: 指定要素
        em.set_key(kaggle_data, 'id')  # specifying the key column in the kaggle dataset
        em.set_key(imdb_data, 'id')  # specifying the key column in the imdb dataset
        em.set_key(C, '_id')  # specifying the key in the candidate set
        em.set_ltable(C, kaggle_data)  # specifying the left table
        em.set_rtable(C, imdb_data)  # specifying the right table
        em.set_fk_rtable(C, 'r_id')  # specifying the column that matches the key in the right table
        em.set_fk_ltable(C, 'l_id')

        # 子步驟C: 攔截工具故障排除
        C[['l_norm_movie_title', 'r_norm_title', 'l_norm_title_year', 'r_norm_year',
           'l_budget', 'r_budget', 'l_content_rating', 'r_mpaa']].head()

        # 子步驟D: 從候選集采樣,label列
        # samplelen = rowCount
        sampled = C.sample(rowCount, random_state=0)

        #增加label列
        # 為了標記抽樣的數據,我們可以在.csv文件中創建一個新的列(我們稱之為label);
        # 如果配對是正確的匹配,則在此欄中填入數值1,否則,填入數值0。為避免文件重疊,讓我們將新文件重命名為labeled.csv。
        list =[]
        for index in xrange(len(sampled.values)):

            tem =float(sampled.values[index][13])
            if tem>0.6:
                list.append(1)
            else:
                list.append(0)
        sampled['label'] =list



        #把采樣數據保存到sampled.csv文件里面
        # sampled.to_csv('./data/sampled.csv', encoding='utf-8')
        sampled.to_csv('./data/sampled.csv')


        # If you would like to avoid labeling the pairs for now, you can download the labled.csv file from
        # BigGorilla using the following command (if you prefer to do it yourself, command the next line)
        # response = urllib.urlretrieve('https://anaconda.org/BigGorilla/datasets/1/download/labeled.csv',
        #                               './data/labeled.csv')
        labeled = em.read_csv_metadata('data/labeled.csv', ltable=kaggle_data, rtable=imdb_data,
                                       fk_ltable='l_id', fk_rtable='r_id', key='_id')
        # tt = labeled.head()

        # 子步驟E: 機器學習算法訓練
        # 現在我們可以使用抽樣的數據集,針對我們的預測任務進行各種機器學習算法訓練。
        # 為此,我們需要將我們的數據集分割為訓練和測試集,然后為我們的預測任務選擇所需的機器學習方法。
        split = em.split_train_test(labeled, train_proportion=0.5, random_state=0)
        train_data = split['train']
        test_data = split['test']

        dt = em.DTMatcher(name='DecisionTree', random_state=0)
        svm = em.SVMMatcher(name='SVM', random_state=0)
        rf = em.RFMatcher(name='RF', random_state=0)
        lg = em.LogRegMatcher(name='LogReg', random_state=0)
        ln = em.LinRegMatcher(name='LinReg')
        nb = em.NBMatcher(name='NaiveBayes')

        # 在應用任何機器學習方法之前,我們需要抽取一組功能。幸運地是,一旦我們指定兩個數據集中的哪些列相互對應,
        # py_entitymatching程序包就可以自動抽取一組功能。指定兩個數據集的列之間的對應性,
        # 將啟動以下代碼片段。然后,它使用py_entitymatching程序包確定各列的類型。
        # 通過考慮(變量l_attr_types和r_attr_types中存儲的)各個數據集中列的類型,
        # 並使用軟件包推薦的編譯器和類似功能,我們可以抽取一組用於抽取功能的說明。
        # 請注意,變量F並非所抽取功能的集合,相反,它會對說明編碼以處理功能。
        attr_corres = em.get_attr_corres(kaggle_data, imdb_data)
        attr_corres['corres'] = [('norm_movie_title', 'norm_title'),
                                 ('norm_title_year', 'norm_year'),
                                 ('content_rating', 'mpaa'),
                                 ('budget', 'budget'),
                                 ]

        l_attr_types = em.get_attr_types(kaggle_data)
        r_attr_types = em.get_attr_types(imdb_data)

        tok = em.get_tokenizers_for_matching()
        sim = em.get_sim_funs_for_matching()

        F = em.get_features(kaggle_data, imdb_data, l_attr_types, r_attr_types, attr_corres, tok, sim)

        # 考慮所需功能的集合F,現在我們可以計算訓練數據的功能值,並找出我們數據中丟失數值的原因。
        # 在這種情況下,我們選擇將丟失值替換為列的平均值。


        train_features = em.extract_feature_vecs(train_data, feature_table=F, attrs_after='label', show_progress=False)
        train_features = em.impute_table(train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         strategy='mean')

        # 使用計算的功能,我們可以評估不同機器學習算法的性能,並為我們的匹配任務選擇最佳的算法

        result = em.select_matcher([ ln, lg,svm,nb,rf, dt], table=train_features,
                                   exclude_attrs=['_id', 'l_id', 'r_id', 'label'], k=5,
                                   target_attr='label', metric='f1', random_state=0)
        print result['cv_stats']

        # 子步驟F: 評估我們的匹配質量

        best_model = result['selected_matcher']

        best_model.fit(table=train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], target_attr='label')

        test_features = em.extract_feature_vecs(test_data, feature_table=F, attrs_after='label', show_progress=False)
        test_features = em.impute_table(test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], strategy='mean')

        # Predict on the test data
        predictions = best_model.predict(table=test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         append=True, target_attr='predicted', inplace=False)

        # Evaluate the predictions
        eval_result = em.eval_matches(predictions, 'label', 'predicted')
        em.print_eval_summary(eval_result)

        # 子步驟G: 使用訓練的模型匹配數據集
        # 現在,我們可以使用訓練的模型對兩個標記進行如下匹配:

        candset_features = em.extract_feature_vecs(C, feature_table=F, show_progress=True)
        candset_features = em.impute_table(candset_features, exclude_attrs=['_id', 'l_id', 'r_id'], strategy='mean')
        predictions = best_model.predict(table=candset_features, exclude_attrs=['_id', 'l_id', 'r_id'],
                                         append=True, target_attr='predicted', inplace=False)
        matches = predictions[predictions.predicted == 1]

        # 請注意,匹配數據幀包含了很多存儲數據集抽取功能的列。以下代碼片段移除了所有非必要的列,並創建一個格式良好的擁有最終形成的整合數據集的數據幀。
        from py_entitymatching.catalog import catalog_manager as cm
        matches = matches[['_id', 'l_id', 'r_id', 'predicted']]
        matches.reset_index(drop=True, inplace=True)
        cm.set_candset_properties(matches, '_id', 'l_id', 'r_id', kaggle_data, imdb_data)
        matches = em.add_output_attributes(matches, l_output_attrs=['movie_title','norm_movie_title', 'norm_title_year', 'budget',
                                                                    'content_rating'],
                                           r_output_attrs=['title','norm_title', 'norm_year', 'budget', 'mpaa'],
                                           l_output_prefix='l_', r_output_prefix='r_',
                                           delete_from_catalog=False)
        matches.drop('predicted', axis=1, inplace=True)
        matches.head()
        # matches.to_csv('./data/finalResult-Magellan.csv', encoding='utf-8')
        # matches.to_csv('./data/finalResult-Magellan.csv')

        titls = []
        for col in matches.columns:
            titls.append(col)
        self.WriteToCsv(titls,matches.values)
        # print str(datetime.datetime.now())[0:19]

    def match_merge_softad(self):
        '''數據匹配合並'''
        left_Candidate_set = ['channel_name1', 'programe_name1', 'brand_name1']
        right_Candidate_set = ['channel_name2', 'programe_name2', 'brand_name2']

        obj = extract_clean_data()
        leftcsvfile = './data/20170708.csv'
        soft_data = obj.get_date_fromCSV(leftcsvfile)

        dir = os.path.join(os.getcwd(), 'data\softAD-1701-1706')
        flist = []
        dir = unicode(dir, 'utf8')
        for (dirpath, dirnames, filenames) in walk(dir):
            flist.extend(filenames)
            break
        for fileName in flist:
            if fileName.find('finalResult') == -1:
                rightcsvfile = str('./data/softAD-1701-1706/') + fileName.encode('utf8')
                monitor_soft_data = obj.get_date_fromCSV(rightcsvfile)
                monitor_soft_data = monitor_soft_data.drop_duplicates(subset=right_Candidate_set, keep='first').copy()
                monitor_soft_data.head()

                data_attempt1 = pd.merge(soft_data, monitor_soft_data, how='inner', left_on=left_Candidate_set,
                                         right_on=right_Candidate_set)

                fp = os.path.basename(rightcsvfile)
                filename = './data/softAD-1701-1706/fmerge_softad-' + fp[0:fp.rindex('.')] + '.csv'
                filename = unicode(filename, 'utf8')
                data_attempt1.to_csv(filename)


    def match_softad_Magellan(self):
        obj = extract_clean_data()
        logfile = os.path.join(os.getcwd(), 'log\\' + time.strftime('%Y-%m-%d') + '.txt')
        log = LogFile.LogFile(logfile)

        # 加載串播單數據
        leftcsvfile = './data/softAD-1701-1706/20170706.csv'
        soft_data = obj.get_date_fromCSV(leftcsvfile)
        log.WriteLog('\r\n')
        log.WriteLog('加載串播單數據:%s' % os.path.basename(leftcsvfile))
        print ('加載串播單數據:%s' % os.path.basename(leftcsvfile))

        dir = os.path.join(os.getcwd(), 'data\softAD-1701-1706')
        flist = []
        dir = unicode(dir, 'utf8')
        for (dirpath, dirnames, filenames) in walk(dir):
            flist.extend(filenames)
            break
        for fileName in flist:
            if fileName.find('finalResult')==-1:
                fn = str('./data/softAD-1701-1706/') + fileName.encode('utf8')
                self.match_softad_data(soft_data,log,leftcsvfile='./data/20170708.csv',rightcsvfile=fn)


    def match_softad_data(self,soft_data,log,leftcsvfile,rightcsvfile,
                          left_Candidate_set=['channel_name1', 'programe_name1', 'brand_name1'],
                          right_Candidate_set=['channel_name2', 'programe_name2', 'brand_name2'],
                          attr_corres_columns=[('channel_name1', 'channel_name2'),('programe_name1', 'programe_name2'),('brand_name1', 'brand_name2'),],
                          csvtitls=['_id', 'l_id', 'r_id', '頻道名稱', '整理節目全稱-廣告項目', '整理品牌', '頻道', '節目名稱', '品牌']):
        '''
        leftcsvfile='./data/20170708.csv'
        rightcsvfile='./data/串播單-T-中央台D006-中央1套(綜合)170101-170630-更新1.csv'
        left_Candidate_set=['channel_name1', 'programe_name1', 'brand_name1']
        right_Candidate_set=['channel_name2', 'programe_name2', 'brand_name2']
        attr_corres_columns=[('channel_name1', 'channel_name2'),('programe_name1', 'programe_name2'),('brand_name1', 'brand_name2'),]
        :param log: log日志
        :param leftcsvfile:
        :param rightcsvfile:
        :param left_Candidate_set:
        :param right_Candidate_set:
        :param attr_corres_columns:
        :return:
        '''


        obj = extract_clean_data()
        # # logfile = os.path.join(os.getcwd(), 'log\\' + time.strftime('%Y-%m-%d') + '.txt')
        # # log = LogFile.LogFile(logfile)
        # # 1、獲取數據
        # # 軟廣數據
        # soft_data = obj.get_date_fromCSV(leftcsvfile)
        # log.WriteLog('\r\n')
        # log.WriteLog('加載串播單數據:%s'%os.path.basename(leftcsvfile))

        log.WriteLog('\r\n')
        # 軟廣告監測報告數據

        monitor_soft_data = obj.get_date_fromCSV(rightcsvfile)
        log.WriteLog('加載軟廣告監測報告數據:%s' % os.path.basename(rightcsvfile))
        print ('加載軟廣告監測報告數據:%s' % os.path.basename(rightcsvfile))
        # 去重復數據
        # soft_data = soft_data.drop_duplicates(subset=left_Candidate_set, keep='first').copy()
        # soft_data.head()
        # 去重復數據
        monitor_soft_data = monitor_soft_data.drop_duplicates(subset=right_Candidate_set, keep='first').copy()
        monitor_soft_data.head()

        soft_data['id'] = range(soft_data.shape[0])
        monitor_soft_data['id'] = range(monitor_soft_data.shape[0])

        # 2、尋找一個候選集(攔截)
        lstlen = len(left_Candidate_set)
        temp = ''
        for i in xrange(lstlen-1):
            temp += soft_data[left_Candidate_set[i]] + ' '
        soft_data['mixture'] = temp+soft_data[left_Candidate_set[lstlen - 1]]

        lstlen = len(right_Candidate_set)
        temp = ''
        for i in xrange(lstlen-1):
            temp += monitor_soft_data[right_Candidate_set[i]] + ' '
        monitor_soft_data['mixture'] = temp + monitor_soft_data[right_Candidate_set[lstlen - 1]]


        # 使用重疊系數連接兩個表。
        C = ssj.overlap_coefficient_join(soft_data, monitor_soft_data, 'id', 'id', 'mixture', 'mixture',
                                         sm.WhitespaceTokenizer(),
                                         l_out_attrs=left_Candidate_set,
                                         r_out_attrs=right_Candidate_set,
                                         threshold=0.65)
        log.WriteLog('正在尋找一個候選集')
        print ('正在尋找一個候選集')
        rowCount = C.shape[0]
        if rowCount <= 5:
            log.WriteLog('文件%s沒有匹配項' % os.path.basename(rightcsvfile))
            print ('文件%s沒有匹配項' % os.path.basename(rightcsvfile))
            return

        # 3、 指定要素
        em.set_key(soft_data, 'id')  # specifying the key column in the kaggle dataset
        em.set_key(monitor_soft_data, 'id')  # specifying the key column in the imdb dataset
        em.set_key(C, '_id')  # specifying the key in the candidate set
        em.set_ltable(C, soft_data)  # specifying the left table
        em.set_rtable(C, monitor_soft_data)  # specifying the right table
        em.set_fk_rtable(C, 'r_id')  # specifying the column that matches the key in the right table
        em.set_fk_ltable(C, 'l_id')
        log.WriteLog('正在指定要素')
        print ('正在指定要素')

        # 4: 攔截工具故障排除
        l_list = ['l_'+ item for item in left_Candidate_set]
        r_list = ['r_' + item for item in right_Candidate_set]
        l_list.extend(r_list)
        C[l_list].head()
        # C[['l_channel_name1', 'r_channel_name2', 'l_programe_name1', 'r_programe_name2',
        #    'l_brand_name1', 'r_brand_name2']].head()
        log.WriteLog('正在攔截工具故障排除')
        print ('正在攔截工具故障排除')

        # 5: 從候選集采樣


        # rowCount = 500
        colmunCount = C.shape[1]
        sampled = C.sample(rowCount, random_state=0)
        # 增加label列
        # 為了標記抽樣的數據,我們可以在.csv文件中創建一個新的列(我們稱之為label);
        # 如果配對是正確的匹配,則在此欄中填入數值1,否則,填入數值0。為避免文件重疊,讓我們將新文件重命名為labeled.csv。
        list = []
        for item in sampled.values:
            tem = float(item[colmunCount-1])
            if tem > 0.6:
                list.append(1)
            else:
                list.append(0)
        sampled['label'] = list

        # 把采樣數據保存到sampled.csv文件里面
        # sampled.to_csv('./data/sampled.csv', encoding='utf-8')
        sampled.to_csv('./data/labeled.csv')

        labeled = em.read_csv_metadata('data/labeled.csv', ltable=soft_data, rtable=monitor_soft_data,
                                       fk_ltable='l_id', fk_rtable='r_id', key='_id')
        log.WriteLog('正在從候選集采樣')
        print ('正在從候選集采樣')

        # 6: 機器學習算法訓練
        # 現在我們可以使用抽樣的數據集,針對我們的預測任務進行各種機器學習算法訓練。
        # 為此,我們需要將我們的數據集分割為訓練和測試集,然后為我們的預測任務選擇所需的機器學習方法。
        log.WriteLog('正在進行機器學習算法訓練')
        print ('正在進行機器學習算法訓練')
        split = em.split_train_test(labeled, train_proportion=0.5, random_state=0)
        train_data = split['train']
        test_data = split['test']

        dt = em.DTMatcher(name='DecisionTree', random_state=0)
        svm = em.SVMMatcher(name='SVM', random_state=0)
        rf = em.RFMatcher(name='RF', random_state=0)
        lg = em.LogRegMatcher(name='LogReg', random_state=0)
        ln = em.LinRegMatcher(name='LinReg')
        nb = em.NBMatcher(name='NaiveBayes')

        # 在應用任何機器學習方法之前,我們需要抽取一組功能。幸運地是,一旦我們指定兩個數據集中的哪些列相互對應,
        # py_entitymatching程序包就可以自動抽取一組功能。指定兩個數據集的列之間的對應性,
        # 將啟動以下代碼片段。然后,它使用py_entitymatching程序包確定各列的類型。
        # 通過考慮(變量l_attr_types和r_attr_types中存儲的)各個數據集中列的類型,
        # 並使用軟件包推薦的編譯器和類似功能,我們可以抽取一組用於抽取功能的說明。
        # 請注意,變量F並非所抽取功能的集合,相反,它會對說明編碼以處理功能。
        attr_corres = em.get_attr_corres(soft_data, monitor_soft_data)
        attr_corres['corres'] = attr_corres_columns

        l_attr_types = em.get_attr_types(soft_data)
        r_attr_types = em.get_attr_types(monitor_soft_data)

        tok = em.get_tokenizers_for_matching()
        sim = em.get_sim_funs_for_matching()

        F = em.get_features(soft_data, monitor_soft_data, l_attr_types, r_attr_types, attr_corres, tok, sim)

        # 考慮所需功能的集合F,現在我們可以計算訓練數據的功能值,並找出我們數據中丟失數值的原因。
        # 在這種情況下,我們選擇將丟失值替換為列的平均值。


        train_features = em.extract_feature_vecs(train_data, feature_table=F, attrs_after='label', show_progress=False)
        train_features = em.impute_table(train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         strategy='mean')

        # 使用計算的功能,我們可以評估不同機器學習算法的性能,並為我們的匹配任務選擇最佳的算法

        # result = em.select_matcher([ln, lg, svm, nb, rf, dt], table=train_features,
        #                            exclude_attrs=['_id', 'l_id', 'r_id', 'label'], k=5,
        #                            target_attr='label', metric='f1', random_state=0)
        result = em.select_matcher([ln,  nb, rf, dt], table=train_features,
                                   exclude_attrs=['_id', 'l_id', 'r_id', 'label'], k=5,
                                   target_attr='label', metric='f1', random_state=0)
        print result['cv_stats']

        # 7: 評估我們的匹配質量
        log.WriteLog('正在進行評估匹配質量')
        print ('正在進行評估匹配質量')
        best_model = result['selected_matcher']

        best_model.fit(table=train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], target_attr='label')

        test_features = em.extract_feature_vecs(test_data, feature_table=F, attrs_after='label', show_progress=False)
        test_features = em.impute_table(test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], strategy='mean')

        # Predict on the test data
        predictions = best_model.predict(table=test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         append=True, target_attr='predicted', inplace=False)

        # Evaluate the predictions
        eval_result = em.eval_matches(predictions, 'label', 'predicted')
        em.print_eval_summary(eval_result)

        # 8: 使用訓練的模型匹配數據集
        # 現在,我們可以使用訓練的模型對兩個標記進行如下匹配:
        log.WriteLog('正在進行用訓練的模型匹配數據集')
        print ('正在進行用訓練的模型匹配數據集')
        candset_features = em.extract_feature_vecs(C, feature_table=F, show_progress=True)
        candset_features = em.impute_table(candset_features, exclude_attrs=['_id', 'l_id', 'r_id'], strategy='mean')
        predictions = best_model.predict(table=candset_features, exclude_attrs=['_id', 'l_id', 'r_id'],
                                         append=True, target_attr='predicted', inplace=False)
        matches = predictions[predictions.predicted == 1]

        # 請注意,匹配數據幀包含了很多存儲數據集抽取功能的列。以下代碼片段移除了所有非必要的列,並創建一個格式良好的擁有最終形成的整合數據集的數據幀。
        from py_entitymatching.catalog import catalog_manager as cm
        matches = matches[['_id', 'l_id', 'r_id', 'predicted']]
        matches.reset_index(drop=True, inplace=True)
        cm.set_candset_properties(matches, '_id', 'l_id', 'r_id', soft_data, monitor_soft_data)
        matches = em.add_output_attributes(matches,
                                           l_output_attrs=left_Candidate_set,
                                           r_output_attrs=right_Candidate_set,
                                           l_output_prefix='l_', r_output_prefix='r_',
                                           delete_from_catalog=False)
        matches.drop('predicted', axis=1, inplace=True)
        matches.head()
        # matches.to_csv('./data/finalResult-Magellan.csv', encoding='utf-8')
        # matches.to_csv('./data/finalResult-Magellan.csv')

        # titls = []
        # for col in matches.columns:
        #     titls.append(col)
        csvtitls=['_id','l_id','r_id','頻道名稱','整理節目全稱-廣告項目','整理品牌','頻道','節目名稱','品牌']
        log.WriteLog('把匹配的最終數據導出到csv文件')
        print ('把匹配的最終數據導出到csv文件')
        fp = os.path.basename(rightcsvfile)
        filename = './data/softAD-1701-1706/finalResult-'+fp[0:fp.rindex('.')] + '.csv'
        filename = unicode(filename,'utf8')
        self.WriteToCsv(csvtitls, matches.values,filename)

        return

#obj = match_merge_data()
# obj.match_merge_Kaggle_IMDB()
# obj.match_merge_Kaggle_IMDB_stringsimjoin()
# obj.match_merge_Kaggle_IMDB_Magellan()
#obj.match_softad_Magellan()
# obj.match_merge_softad()

##########################################################################################

#coding=utf8
#數據匹配和合並

import os
import datetime
import time
import re
import csv
import pandas as pd
from os import walk
import urllib
import py_stringsimjoin as ssj
import py_stringmatching as sm

from pandas.core.frame import DataFrame
from extract_clean import extract_clean_data
import py_entitymatching as em
import LogFile

class match_merge_data:
    def __init__(self):
        pass

    def WriteToCsv(self, titls, data,filename='./data/finalResult-Magellan.csv'):

        # csvfile = os.path.join(os.getcwd(), 'csvtest.csv')
        with open(filename, 'wb') as f:
            writer = csv.writer(f)
            # 標題
            writer.writerow(titls)
            for item in data:
                # 內容
                writer.writerow(item)

    def match_merge_list(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        genreslist = obj.extract_genreslist()
        ratinglist = obj.extract_ratinglist()
        print ratinglist.shape[0]
        print genreslist.shape[0]
        brief_imdb_data = pd.merge(ratinglist, genreslist, how='inner', on=['norm_movie', 'year'])
        brief_imdb_data.head()
        print brief_imdb_data.shape[0]


    def match_merge_Kaggle_IMDB(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()
        # print kaggle_data.shape[0] #4919
        # print imdb_data.shape[0] #869178
        # 方法1
        data_attempt1 = pd.merge(imdb_data, kaggle_data, how='inner', left_on=['norm_title', 'norm_year'],
                                 right_on=['norm_movie_title', 'norm_title_year'])
        # print data_attempt1.shape[0] #4261
        data_attempt1.to_csv('./data/finalResult-IMDB.csv')


    def match_merge_Kaggle_IMDB_stringsimjoin(self):
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()

        # 方法2
        imdb_data['id'] = range(imdb_data.shape[0])
        kaggle_data['id'] = range(kaggle_data.shape[0])
        #使用編輯距離度量來連接兩個表。從左表和右表找到元組,使編輯連接屬性之間的距離滿足輸入條件閾
        #。 例如,如果比較運算符是'<=',則找到元組對,其編碼距離是字符串之間的值連接屬性小於或等於輸入閾值,as在“閾值”中指定。
        similar_titles = ssj.edit_distance_join(imdb_data, kaggle_data, 'id', 'id', 'norm_title',
                                                'norm_movie_title', l_out_attrs=['title','norm_title', 'norm_year'],
                                                r_out_attrs=['movie_title','norm_movie_title', 'norm_title_year'], threshold=1)
        # selecting the entries that have the same production year
        data_attempt2 = similar_titles[similar_titles.r_norm_title_year == similar_titles.l_norm_year]
        data_attempt2.to_csv('./data/finalResult-stringsimjoin.csv')
        # data_attempt2.to_csv('./data/finalResult-stringsimjoin.csv', encoding='utf-8')
        # print data_attempt2.shape[0]#4696
        # print data_attempt3.shape[0]  # 10525

    def match_merge_Kaggle_IMDB_Magellan(self):
        # print str(datetime.datetime.now())[0:19]
        '''數據匹配合並'''
        obj = extract_clean_data()
        kaggle_data = obj.extract_kaggle_dataset()
        imdb_data = obj.extract_imdb_dataset()

        imdb_data['id'] = range(imdb_data.shape[0])
        kaggle_data['id'] = range(kaggle_data.shape[0])

        # 方法3
        # 子步驟A: 尋找一個候選集(攔截)
        # repeating the same thing for the Kaggle dataset
        ssj.dataframe_column_to_str(kaggle_data, 'budget', inplace=True)
        kaggle_data['mixture'] = kaggle_data['norm_movie_title'] + ' ' + kaggle_data['norm_title_year'] + kaggle_data['budget']

        # transforming the "budget" column into string and creating a new **mixture** column
        ssj.dataframe_column_to_str(imdb_data, 'budget', inplace=True)
        imdb_data['mixture'] = imdb_data['norm_title'] + ' ' +          imdb_data['norm_year'] + ' ' +    imdb_data['budget']

        #使用重疊系數連接兩個表。
        C = ssj.overlap_coefficient_join(kaggle_data, imdb_data, 'id', 'id', 'mixture', 'mixture',
                                         sm.WhitespaceTokenizer(),
                                         l_out_attrs=['movie_title','norm_movie_title', 'norm_title_year', 'duration',
                                                      'budget', 'content_rating'],
                                         r_out_attrs=['title','norm_title', 'norm_year', 'length', 'budget', 'mpaa'],
                                         threshold=0.65)
        # C.shape()
        rowCount = C.shape[0] #34
        # print C.shape[0]

        # 子步驟B: 指定要素
        em.set_key(kaggle_data, 'id')  # specifying the key column in the kaggle dataset
        em.set_key(imdb_data, 'id')  # specifying the key column in the imdb dataset
        em.set_key(C, '_id')  # specifying the key in the candidate set
        em.set_ltable(C, kaggle_data)  # specifying the left table
        em.set_rtable(C, imdb_data)  # specifying the right table
        em.set_fk_rtable(C, 'r_id')  # specifying the column that matches the key in the right table
        em.set_fk_ltable(C, 'l_id')

        # 子步驟C: 攔截工具故障排除
        C[['l_norm_movie_title', 'r_norm_title', 'l_norm_title_year', 'r_norm_year',
           'l_budget', 'r_budget', 'l_content_rating', 'r_mpaa']].head()

        # 子步驟D: 從候選集采樣,label列
        # samplelen = rowCount
        sampled = C.sample(rowCount, random_state=0)

        #增加label列
        # 為了標記抽樣的數據,我們可以在.csv文件中創建一個新的列(我們稱之為label);
        # 如果配對是正確的匹配,則在此欄中填入數值1,否則,填入數值0。為避免文件重疊,讓我們將新文件重命名為labeled.csv。
        list =[]
        for index in xrange(len(sampled.values)):

            tem =float(sampled.values[index][13])
            if tem>0.6:
                list.append(1)
            else:
                list.append(0)
        sampled['label'] =list



        #把采樣數據保存到sampled.csv文件里面
        # sampled.to_csv('./data/sampled.csv', encoding='utf-8')
        sampled.to_csv('./data/sampled.csv')


        # If you would like to avoid labeling the pairs for now, you can download the labled.csv file from
        # BigGorilla using the following command (if you prefer to do it yourself, command the next line)
        # response = urllib.urlretrieve('https://anaconda.org/BigGorilla/datasets/1/download/labeled.csv',
        #                               './data/labeled.csv')
        labeled = em.read_csv_metadata('data/labeled.csv', ltable=kaggle_data, rtable=imdb_data,
                                       fk_ltable='l_id', fk_rtable='r_id', key='_id')
        # tt = labeled.head()

        # 子步驟E: 機器學習算法訓練
        # 現在我們可以使用抽樣的數據集,針對我們的預測任務進行各種機器學習算法訓練。
        # 為此,我們需要將我們的數據集分割為訓練和測試集,然后為我們的預測任務選擇所需的機器學習方法。
        split = em.split_train_test(labeled, train_proportion=0.5, random_state=0)
        train_data = split['train']
        test_data = split['test']

        dt = em.DTMatcher(name='DecisionTree', random_state=0)
        svm = em.SVMMatcher(name='SVM', random_state=0)
        rf = em.RFMatcher(name='RF', random_state=0)
        lg = em.LogRegMatcher(name='LogReg', random_state=0)
        ln = em.LinRegMatcher(name='LinReg')
        nb = em.NBMatcher(name='NaiveBayes')

        # 在應用任何機器學習方法之前,我們需要抽取一組功能。幸運地是,一旦我們指定兩個數據集中的哪些列相互對應,
        # py_entitymatching程序包就可以自動抽取一組功能。指定兩個數據集的列之間的對應性,
        # 將啟動以下代碼片段。然后,它使用py_entitymatching程序包確定各列的類型。
        # 通過考慮(變量l_attr_types和r_attr_types中存儲的)各個數據集中列的類型,
        # 並使用軟件包推薦的編譯器和類似功能,我們可以抽取一組用於抽取功能的說明。
        # 請注意,變量F並非所抽取功能的集合,相反,它會對說明編碼以處理功能。
        attr_corres = em.get_attr_corres(kaggle_data, imdb_data)
        attr_corres['corres'] = [('norm_movie_title', 'norm_title'),
                                 ('norm_title_year', 'norm_year'),
                                 ('content_rating', 'mpaa'),
                                 ('budget', 'budget'),
                                 ]

        l_attr_types = em.get_attr_types(kaggle_data)
        r_attr_types = em.get_attr_types(imdb_data)

        tok = em.get_tokenizers_for_matching()
        sim = em.get_sim_funs_for_matching()

        F = em.get_features(kaggle_data, imdb_data, l_attr_types, r_attr_types, attr_corres, tok, sim)

        # 考慮所需功能的集合F,現在我們可以計算訓練數據的功能值,並找出我們數據中丟失數值的原因。
        # 在這種情況下,我們選擇將丟失值替換為列的平均值。


        train_features = em.extract_feature_vecs(train_data, feature_table=F, attrs_after='label', show_progress=False)
        train_features = em.impute_table(train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         strategy='mean')

        # 使用計算的功能,我們可以評估不同機器學習算法的性能,並為我們的匹配任務選擇最佳的算法

        result = em.select_matcher([ ln, lg,svm,nb,rf, dt], table=train_features,
                                   exclude_attrs=['_id', 'l_id', 'r_id', 'label'], k=5,
                                   target_attr='label', metric='f1', random_state=0)
        print result['cv_stats']

        # 子步驟F: 評估我們的匹配質量

        best_model = result['selected_matcher']

        best_model.fit(table=train_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], target_attr='label')

        test_features = em.extract_feature_vecs(test_data, feature_table=F, attrs_after='label', show_progress=False)
        test_features = em.impute_table(test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'], strategy='mean')

        # Predict on the test data
        predictions = best_model.predict(table=test_features, exclude_attrs=['_id', 'l_id', 'r_id', 'label'],
                                         append=True, target_attr='predicted', inplace=False)

        # Evaluate the predictions
        eval_result = em.eval_matches(predictions, 'label', 'predicted')
        em.print_eval_summary(eval_result)

        # 子步驟G: 使用訓練的模型匹配數據集
        # 現在,我們可以使用訓練的模型對兩個標記進行如下匹配:

        candset_features = em.extract_feature_vecs(C, feature_table=F, show_progress=True)
        candset_features = em.impute_table(candset_features, exclude_attrs=['_id', 'l_id', 'r_id'], strategy='mean')
        predictions = best_model.predict(table=candset_features, exclude_attrs=['_id', 'l_id', 'r_id'],
                                         append=True, target_attr='predicted', inplace=False)
        matches = predictions[predictions.predicted == 1]

        # 請注意,匹配數據幀包含了很多存儲數據集抽取功能的列。以下代碼片段移除了所有非必要的列,並創建一個格式良好的擁有最終形成的整合數據集的數據幀。
        from py_entitymatching.catalog import catalog_manager as cm
        matches = matches[['_id', 'l_id', 'r_id', 'predicted']]
        matches.reset_index(drop=True, inplace=True)
        cm.set_candset_properties(matches, '_id', 'l_id', 'r_id', kaggle_data, imdb_data)
        matches = em.add_output_attributes(matches, l_output_attrs=['movie_title','norm_movie_title', 'norm_title_year', 'budget',
                                                                    'content_rating'],
                                           r_output_attrs=['title','norm_title', 'norm_year', 'budget', 'mpaa'],
                                           l_output_prefix='l_', r_output_prefix='r_',
                                           delete_from_catalog=False)
        matches.drop('predicted', axis=1, inplace=True)
        matches.head()
        # matches.to_csv('./data/finalResult-Magellan.csv', encoding='utf-8')
        # matches.to_csv('./data/finalResult-Magellan.csv')

        titls = []
        for col in matches.columns:
            titls.append(col)
        self.WriteToCsv(titls,matches.values)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM