胡世洋,劉威
(賀州學(xué)院,廣西 賀州 542899)
隨著我國農(nóng)業(yè)現(xiàn)代化的加速推進(jìn)[1],農(nóng)業(yè)產(chǎn)業(yè)化、市場化程度的提高,農(nóng)產(chǎn)品數(shù)據(jù)的規(guī)模和復(fù)雜程度不斷增加,這給農(nóng)產(chǎn)品生產(chǎn)和流通帶來了前所未有的機(jī)遇和挑戰(zhàn)。然而,這些數(shù)據(jù)來源多樣,存在規(guī)范化、標(biāo)準(zhǔn)化程度低等問題,這給數(shù)據(jù)的處理和分析帶來了很大的難度。為了更好地理解和應(yīng)用農(nóng)產(chǎn)品數(shù)據(jù),研究者們已經(jīng)開始探索和應(yīng)用各種數(shù)據(jù)處理和分析方法,其中基于Pandas 庫的數(shù)據(jù)預(yù)處理方法已逐漸成為一個(gè)熱門領(lǐng)域。Pandas 作為一種快速、靈活、高效的數(shù)據(jù)處理和分析工具,在清洗、去重、缺失值處理、異常值處理、特征提取等方面都有著得天獨(dú)厚的優(yōu)勢[2]。因此,本文旨在應(yīng)用Pandas 庫中的各種數(shù)據(jù)處理方法,以實(shí)現(xiàn)對(duì)農(nóng)產(chǎn)品產(chǎn)銷數(shù)據(jù)快速、準(zhǔn)確和可靠地處理。
收集來的農(nóng)產(chǎn)品數(shù)據(jù)往往需要二次加工,其原因包括以下幾個(gè)方面:第一,農(nóng)作物成熟之后也可以成為農(nóng)產(chǎn)品的一部分,所以農(nóng)作物數(shù)據(jù)表有時(shí)候需要與農(nóng)產(chǎn)品數(shù)據(jù)表合并在一起分析。第二,需要將原來農(nóng)產(chǎn)品信息表與農(nóng)產(chǎn)品產(chǎn)量表合并在一起形成一個(gè)更全面的農(nóng)產(chǎn)品數(shù)據(jù)表。第三,需要將農(nóng)產(chǎn)品數(shù)據(jù)表、商家數(shù)據(jù)表、顧客數(shù)據(jù)表、商品銷售表合并為一個(gè)寬表。第四,需要將數(shù)據(jù)表中記錄重復(fù)的、特征重復(fù)的數(shù)據(jù)刪除掉。第五,需要用可信賴的方式填充某些為空的字段值。第六,需要用可信賴的方式將明顯脫離正常范圍的字段值糾正到正常范圍。第七,需要將不同量綱的字段標(biāo)準(zhǔn)化處理。第八,需要將非連續(xù)字段轉(zhuǎn)換成虛擬變量[3]。第九,需要將連續(xù)數(shù)值離散化從而利于回歸分析。由于Pandas 可以高效地處理數(shù)據(jù)集。所以要以Python作為開發(fā)語言,以Pandas為數(shù)據(jù)分析工具來解決這些問題。
由于數(shù)據(jù)存放在MySQL數(shù)據(jù)庫中,所以要連接到MySQL數(shù)據(jù)庫。首先安裝pymysql工具包。其次利用sqlalchemy 庫中的create_engine 函數(shù)建立Python 程序與MySQL 數(shù)據(jù)庫的連接[4]。最后利用Pandas 中的read_sql_table讀取MySQL數(shù)據(jù)庫中的任意數(shù)據(jù)表。
1) 縱向堆疊
農(nóng)產(chǎn)品既包括農(nóng)作物又包括對(duì)農(nóng)作物進(jìn)行二次加工過的產(chǎn)品,因此農(nóng)產(chǎn)品應(yīng)包括農(nóng)作物里的內(nèi)容。采用縱向堆疊的方式將農(nóng)作物數(shù)據(jù)表的信息堆疊進(jìn)農(nóng)產(chǎn)品數(shù)據(jù)表之中。首先連接到MySQL數(shù)據(jù)庫,把農(nóng)產(chǎn)品數(shù)據(jù)表和農(nóng)作品數(shù)據(jù)表讀出來并放在DataFrame對(duì)象里面。其次使用Pandas 中的concat 函數(shù)來實(shí)現(xiàn)堆疊,設(shè)axis=0 可實(shí)現(xiàn)縱向堆疊,由于農(nóng)產(chǎn)品和農(nóng)作物的數(shù)據(jù)表字段未必完全一致,在此僅取它們兩張表字段的交集,因此將join參數(shù)設(shè)置為inner。最后將堆疊后形成的DataFrame 對(duì)象能過Pandas 中的to_sql 函數(shù)重新寫回到MySQL數(shù)據(jù)庫中的農(nóng)產(chǎn)品數(shù)據(jù)表,此時(shí)設(shè)置if_exists 參數(shù)值為replace,從而刷新整個(gè)數(shù)據(jù)表中的數(shù)據(jù),縱向堆疊過程如圖1所示。
圖1 縱向堆疊示意圖
2) 橫向合并
原來收集的農(nóng)產(chǎn)品數(shù)據(jù)表未涉及數(shù)量級(jí)別的字段,而農(nóng)戶產(chǎn)量統(tǒng)計(jì)表中涉及農(nóng)戶所管理的農(nóng)產(chǎn)品數(shù)量內(nèi)容。如果能將這兩個(gè)數(shù)據(jù)表合并成一個(gè)表,那么所生成的新的數(shù)據(jù)表將具備農(nóng)產(chǎn)品特性和數(shù)量兩種類別的字段。這里采用橫向堆疊的方式來解決這個(gè)問題。將農(nóng)產(chǎn)品數(shù)據(jù)表和農(nóng)戶產(chǎn)量統(tǒng)計(jì)表在X 軸上進(jìn)行拼接。首先連接到MySQL數(shù)據(jù)庫,把農(nóng)產(chǎn)品數(shù)據(jù)表和農(nóng)戶產(chǎn)量統(tǒng)計(jì)表讀出來并放在DataFrame對(duì)象里面。其次使用Pandas中的concat函數(shù)來實(shí)現(xiàn)堆疊,設(shè)axis=1實(shí)現(xiàn)橫向堆疊。在堆疊時(shí)排除掉農(nóng)戶產(chǎn)量統(tǒng)計(jì)表中的編號(hào)一列。最后將堆疊后形成的新的DataFrame 對(duì)象重新寫回到MySQL 數(shù)據(jù)庫中,橫向堆疊過程如圖2所示。
圖2 橫向堆疊示意圖
3) 主鍵合并
在數(shù)據(jù)分析時(shí)需要多個(gè)表連接在一起形成一個(gè)寬表。主鍵合并就是將多個(gè)數(shù)據(jù)集通過它們關(guān)聯(lián)的鍵連接起來。本文將以農(nóng)產(chǎn)品數(shù)據(jù)表、商家數(shù)據(jù)表、顧客數(shù)據(jù)表、商品銷售表為例進(jìn)行主鍵合并。利用農(nóng)產(chǎn)品數(shù)據(jù)表中的主鍵“編號(hào)”和商品銷售表中的外鍵“商品”,可以將兩個(gè)表連接起來。利用商家數(shù)據(jù)表中的主鍵“編號(hào)”和商品銷售表中的外鍵“賣家”,可以將兩個(gè)表連接起來。利用顧客數(shù)據(jù)表中的主鍵“編號(hào)”和商品銷售表中的外鍵“買家”,可以將兩個(gè)表連接起來。在這個(gè)過程中,使用Pandas 中的merge 函數(shù)來實(shí)現(xiàn)數(shù)據(jù)的主鍵合并。最后將主鍵合并后形成的寬表重新寫回到MySQL 數(shù)據(jù)庫中,主鍵合并過程如圖3所示。
圖3 主鍵合并示意圖
1) 記錄重復(fù)
在數(shù)據(jù)收集過程中由于數(shù)據(jù)的來源是多方面的,而且前期數(shù)據(jù)模型的設(shè)計(jì)難免有不周到地方,這樣就會(huì)造成數(shù)據(jù)的部分重復(fù)。記錄重復(fù)在數(shù)據(jù)重復(fù)中比較常見,那些重復(fù)出現(xiàn)的數(shù)據(jù)記錄需要被刪除掉[5]。在這個(gè)過程中需要使用Pandas中的drop_duplicates函數(shù)來實(shí)現(xiàn)記錄去重。由于寬表的字段特別多,全面匹配才認(rèn)為是重復(fù)的做法是不可取的。因此選取幾個(gè)重要的字段比如商品編號(hào)、賣家、買家和交易時(shí)間,作為是否重復(fù)的判斷依據(jù)。由于同一交易時(shí)間不可能出現(xiàn)兩次相同的交易,所以這些選取的字段出現(xiàn)了重復(fù)就認(rèn)為這條記錄是重復(fù)的,可以被刪除掉。最后將去重后的DataFrame 對(duì)象能過Pandas 中的to_sql 函數(shù)重新寫回到MySQL數(shù)據(jù)庫中農(nóng)產(chǎn)品銷售寬表,記錄重復(fù)如圖4所示。
圖4 記錄重復(fù)示意圖
2) 特征重復(fù)
將農(nóng)產(chǎn)品數(shù)據(jù)表、商家數(shù)據(jù)表、顧客數(shù)據(jù)表、商品銷售表四合表進(jìn)行主鍵合并,從而形成農(nóng)產(chǎn)品銷售寬表。這個(gè)寬表里面的數(shù)據(jù)必然存在冗余的情況。例如:原農(nóng)產(chǎn)品數(shù)據(jù)表中的“編號(hào)”和原商品銷售表中的“商品”這兩個(gè)字段在新的寬表里面顯然是重復(fù)的。這些冗余的字段不僅造空間的浪費(fèi)而且不利于后面的數(shù)據(jù)分析與挖掘。所以這些冗余字段需要被找出來并刪除掉。在這個(gè)過程中,需要建立一個(gè)行和列都等于農(nóng)產(chǎn)品銷售寬表列數(shù)的布爾數(shù)組。通過DataFrame.equals 方法將農(nóng)產(chǎn)品銷售寬表的不同列進(jìn)行比較,如果值都相等就將布爾數(shù)組對(duì)應(yīng)的行和列的元素置為“真”,否則置為“假”,這樣就得到一個(gè)布爾矩陣。然后遍歷這個(gè)布爾矩陣,將重復(fù)的字段找出來,并使用Pandas的drop函數(shù)刪掉。最后將去重后的DataFrame 對(duì)象寫回到MySQL 數(shù)據(jù)庫中,特征重復(fù)如圖5所示。
圖5 特征重復(fù)示意圖
3) 檢測與處理缺失值
收集到的數(shù)據(jù)可能存在缺失值,即某幾條記錄的某些字段值為空。解決這些空值有多種方法。比如刪除法、替換法和插值法等。刪除法是利用Pandas中的dropna 方法將含有空值的記錄刪除掉。這樣做存在明顯不合理之處,存在空值的記錄不一定都要?jiǎng)h除,該記錄的其他非空字段很可能也存在重要的研究價(jià)值。替換法則是利用該字段下的平均數(shù)、中位數(shù)等統(tǒng)計(jì)量來填充記錄中的空值。利用平均數(shù)、中位數(shù)等來填充空值可能會(huì)影響數(shù)據(jù)的標(biāo)準(zhǔn)差,導(dǎo)致信息的波動(dòng)。插值法是通過求解多項(xiàng)式來得到一個(gè)值,然后讓這個(gè)值來替換記錄中的空值。此處采用插值法來解決這個(gè)問題。要使用插值法需要找到與本字段相關(guān)的另一個(gè)沒有空值的字段。以商品信息表為例,存貨量存在空值,找到跟存貨量有一定關(guān)聯(lián)的字段,即總產(chǎn)量。首先要根據(jù)總產(chǎn)量和存貨量這兩個(gè)字段擬合出來一個(gè)多項(xiàng)式函數(shù)。再根據(jù)存在存貨量為空的記錄對(duì)應(yīng)的總產(chǎn)量和多項(xiàng)式函數(shù)計(jì)算出該記錄存貨量的值,將這個(gè)值再插入數(shù)據(jù)表里面。
4) 檢測與處理異常值
在農(nóng)產(chǎn)品數(shù)據(jù)表里面也會(huì)出現(xiàn)明顯偏離正常的數(shù)值。這些數(shù)值可能來源于數(shù)據(jù)收集時(shí)的錯(cuò)誤,或者程序調(diào)試時(shí)遺留的臟數(shù)據(jù)。這樣的數(shù)值也稱為離群點(diǎn)[6]。這些離群點(diǎn)的存在會(huì)給以后的數(shù)據(jù)分析帶來極大的隱患,甚至?xí)?dǎo)致預(yù)測的結(jié)果出現(xiàn)偏差??梢允褂?σ 原則來進(jìn)行數(shù)值的異常檢測,也可以使用箱線圖分析法來進(jìn)行數(shù)值異常檢測。此處以農(nóng)產(chǎn)品的銷售金額為例,使用箱線圖分析法來闡述異常數(shù)值檢測與矯正過程。首先從數(shù)據(jù)庫讀取農(nóng)產(chǎn)品銷售表。其次計(jì)算箱線圖的五個(gè)統(tǒng)計(jì)量。使用quantile函數(shù)再加上0.25 的參數(shù)可以計(jì)算出下四分?jǐn)?shù)(即QU) ,如果參數(shù)改成0.75可算以上四分?jǐn)?shù)(即QL) 。由上四分?jǐn)?shù)減下四分?jǐn)?shù)可計(jì)算機(jī)中位數(shù)(即IQR) 。利用公式QU +1.5×IQR 可計(jì)算出最大值,如果數(shù)值超過了最大值就用上四分?jǐn)?shù)來替代其原有值。利用公式QL-1.5 ×IQR可計(jì)算出最小值,如果數(shù)值超過了最小值就下四分?jǐn)?shù)來替代其原有值。最后將新的DataFrame對(duì)象寫回到數(shù)據(jù)庫當(dāng)中,日銷金額箱線圖如圖6所示。
圖6 農(nóng)產(chǎn)品日銷金額箱線圖
想要根據(jù)農(nóng)產(chǎn)品的存貨量、總產(chǎn)量和日銷量等這些因素來分析農(nóng)戶的年度利潤就會(huì)面臨特征字段量綱不同的問題。存貨量和總產(chǎn)量的數(shù)值遠(yuǎn)遠(yuǎn)高于日銷量。但是日銷量對(duì)年度利潤的影響也很大。為了不影響以后數(shù)據(jù)分析的準(zhǔn)確性,就需要消除這些量綱的差異,即進(jìn)行數(shù)據(jù)標(biāo)準(zhǔn)化處理。數(shù)據(jù)標(biāo)準(zhǔn)化處理常用的方法有離差標(biāo)準(zhǔn)化[7]、標(biāo)準(zhǔn)差標(biāo)準(zhǔn)化、小數(shù)定標(biāo)標(biāo)準(zhǔn)化等。為了不改變數(shù)據(jù)原有的分布情況,這里采用小數(shù)定標(biāo)標(biāo)準(zhǔn)化處理方法[8]。小數(shù)定標(biāo)標(biāo)準(zhǔn)化轉(zhuǎn)換公式如公式1所示:
通過這個(gè)公式可以看出小數(shù)定標(biāo)標(biāo)準(zhǔn)化的關(guān)鍵是k值的確定。把待處理的這列數(shù)據(jù)作為一個(gè)Series對(duì)象。再對(duì)Series對(duì)象里面數(shù)值的絕對(duì)值的最大值求10 的對(duì)數(shù)作為k 的取值。按照轉(zhuǎn)換公式對(duì)相關(guān)字段進(jìn)行標(biāo)準(zhǔn)化處理,最后將處理的DataFrame 對(duì)象通過tosql函數(shù)重新寫回?cái)?shù)據(jù)庫中。
1) 啞變量處理
為分析不同地區(qū)農(nóng)產(chǎn)品價(jià)格的差異,把字段“市”進(jìn)行啞變量處理。因?yàn)椤笆小弊鳛橐粋€(gè)地區(qū)類別的字段并非連續(xù)型的。非連續(xù)字段的值不能做加減計(jì)算,不利于以后對(duì)農(nóng)產(chǎn)品銷售情況進(jìn)行回歸分析,因此需要將“市”這個(gè)區(qū)域類別轉(zhuǎn)換成虛擬變量。再利用這些虛擬變量做回歸分析。這個(gè)過程需要利用Pandas的get_dummies 函數(shù)轉(zhuǎn)換成啞變量DataFrame,將啞變量DataFrame與原商品信息進(jìn)行橫向合并。最后將最終的DataFrame 對(duì)象寫回?cái)?shù)據(jù)當(dāng)中,啞變量處理過程如圖7所示。
圖7 啞變量處理示意圖
2) 離散化連續(xù)性數(shù)據(jù)
分析農(nóng)產(chǎn)品在8月份的銷量變化情況需要將7、8月份農(nóng)產(chǎn)品的銷量數(shù)據(jù)離散化。按照銷售量的大小將其分成幾個(gè)區(qū)間,然后用變量表示每個(gè)區(qū)間的銷售量范圍,啞變量作為自變量,以時(shí)間為因變量,進(jìn)行回歸分析,以評(píng)估銷售量區(qū)間之間的相關(guān)性和趨勢。通過這種方法,可以更好地理解銷售量的變化趨勢和影響因素。在具體處理過程中,利用聚類分析法將商品信息統(tǒng)計(jì)表中的銷量一列數(shù)值劃分為5個(gè)類別,形成一個(gè)新的Series。然后將新的值再進(jìn)行啞變量處理。將處理后形成的DataFrame再與商品信息統(tǒng)計(jì)表進(jìn)行橫向堆疊。最后將形成的最終DataFrame寫入數(shù)據(jù)庫當(dāng)中,離散化處理過程如圖8所示。
圖8 離散化連續(xù)性數(shù)據(jù)示意圖
本文介紹如何利用Pandas 技術(shù)來實(shí)現(xiàn)農(nóng)產(chǎn)品產(chǎn)銷數(shù)據(jù)預(yù)處理。經(jīng)過預(yù)處理之后的數(shù)據(jù)可以更為方便地被理解和分析。這也為將來對(duì)農(nóng)產(chǎn)品市場的預(yù)測、供應(yīng)鏈的優(yōu)化、市場競爭力的提升提供技術(shù)支持,這也利于農(nóng)產(chǎn)品的市場監(jiān)管和市場推廣。同時(shí)探索、研究和應(yīng)用更加先進(jìn)的數(shù)據(jù)處理方法,也是農(nóng)業(yè)數(shù)據(jù)化建設(shè)和現(xiàn)代化進(jìn)程的必然要求。