1. 程式人生 > >資料處理2.0

資料處理2.0

之前的在1.0版本中,我處理的是一個只有[54 rows,547columns]的比較小的資料集,當遇到較大的資料集時([197896 rows,547columns]),程式處理遇到了問題。比如:資料讀取比較緩慢,之前跑大概1-2s,後來需要將近30min才能出結果;輸出的結果檔案太大,導致python報錯無法輸出;資料集又出現了新的資料,需要進一步處理。
問題:

  • 輸出檔案太大
    原來的處理辦法是df = pd.read_excel、df.to_excel
    報錯出現了這樣的提示:
    “filesize would require ZIP64 extensions”
    嘗試找了一下python怎樣壓縮檔案然後輸出,找到了這樣的方法:
    參考:
    https://zhuanlan.zhihu.com/p/34420427?utm_source=qq&utm_medium=social

    得到了這樣的程式碼:
df_float = df.select_dtypes(include=['float'])
converted_float =df_float.apply(pd.to_numeric,downcast='float')
df_int = df.select_dtypes(include=['int'])
converted_int =df_int.apply(pd.to_numeric,downcast='unsigned')

df[converted_int .columns] = converted_int
df[converted_float .columns] = converted_float

之後我發現:這段程式碼不僅沒有壓縮結果資料,反而使得結果檔案更大了……究竟是怎麼回事,可能得之後深究;
現在另尋辦法——我又在偶然間意外發現可以通過輸出到csv檔案得到結果,於是我總結了一個“規律”:csv檔案要比excel檔案小,因此程式碼修改為:df = pd.read_excel、df.to_csv
這樣就不會報錯了

  • 新的特殊資料和解決辦法
    歲數一列出現了異常值:‘歲’及空資料
    解決方案:需要將異常值置為空值,即填充-1000
    修改函式如下:
def convert(value,data1,data2):
    """
    轉換字串string1為string2
    """
    if isinstance(value,str):
        if(value.find(data1) != -1):
            value = value.replace(data1, data2)
            if value == '':
                value = '-1000'
            value = float(value)
    return value
df['AGE_INPUT'] = df['AGE_INPUT'].apply(convert,data1 = '歲',data2 = '')

全表資料出現一個單位的作為異常值處理,填充-1000:

Units=['mmol/l','mmHg']
def DelUnits(value):
    """
    刪除單位
    """
    if isinstance(value,str):        
        for units in Units:
            if value == units:
                value = -1000.0
                break
    return value
df = df.applymap(DelUnits)

資料中出現的帶年、月、日的資料和帶有’/'的資料都作為異常資料處理,做統一化處理都填充-1000:

#全表修改/,分數等異常值為空值處理
#異常值列表
Outliers = ['/','年','月','日']
def CharConvert(value):
    if isinstance(value,str):
        for outlier in Outliers:
            if(value.find(outlier) != -1):
                value = -1000.0
                break
    return value
df = df.applymap(CharConvert)

在應用中發現當資料格式為X年X月X日時,讀入DataFrame後存入的是一個整數,經過試驗發現1900年1月1日對應的數是1,此後的日期對應的數依次遞增,而1900年之前的日期則以字串的方式(X/X/X)存入DataFrame,因此對1900之前的日期的處理可以歸結成對/的處理 ,而對1900之後的日期的處理只能將dataframe裡超出1000的資料(即1000作為閾值,視具體情況而定)視作異常值,這樣基本不會影響正常的資料,還去除了表中的日期(表裡的日期都是2000年以後)。為了方便,在刪除單位遍歷全表時就達成對日期的處理(注意保留ID一列不被修改),程式碼修改如下:

#全表處理單位和日期異常值
Units=['mmol/l','mmHg']
#先保留ID
IDtemp = df[df.columns[0:3]]
def DelUnits(value):
    """
    刪除單位
    """
    if isinstance(value,str):        
        for units in Units:
            if value == units:
                value = -1000.0
                break
    else:
        if value > 1000:
            value = -1000.0
    return value
df = df.applymap(DelUnits)
df[df.columns[0:3]] = IDtemp

使用正則表示式處理>和<,出現了<X↓
形式的資料,原來的函式不好處理,程式碼如下:

global pattern_s1
global pattern_s2
pattern_s1 = re.compile('<(\d?\.?\d+)')
pattern_s2 = re.compile('>(\d?\.?\d+)')
#全表修改<,>
def DataConvert(value):
    if isinstance(value,str):
        p = re.findall(pattern_s1,value)
        if p == []:
            p = re.findall(pattern_s2,value)
        if p != []:
            value = float(p[0])
    return value
df = df.applymap(DataConvert)

更新後的程式碼如附件