safecastデータセットのデータ洗浄

56536 ワード

Pythonによるデータ洗浄作業記録
  • Safecastデータセット紹介
  • データ初期フォーマット
  • データ仕上げ
  • Safecastデータセットの紹介
    Safecastは、周囲の放射線値情報をパケットで収集し、サーバでまとめて処理した後、地図上に表示する公益組織によって、身近な環境に注目させるために作成されたデータセットで、safecastの公式サイトからダウンロードしたデータセットを処理し、その中の異型データを除去し、機械学習操作を容易にすることを目的としています.
    データ初期フォーマット
    公式サイトからダウンロードしたデータセットのサイズは16 Gで、13億件のデータがあり、これらのデータのヘッダーは以下の通りである.
    Captured Time,Latitude,Longitude,Value,Unit,Location Name,Device ID,MD5Sum,Height,Surface,Radiation,Uploaded Time,Loader ID
    データ量が大きいため、windows環境でsplitというツールを使用してファイルを小ファイルに分割し、分割した結果、最初のファイルを除いて残りのファイルにヘッダーが付いていないため、以下のPythonコードを使用して残りのファイルにヘッダーを追加します.
     with open(filename, 'r', encoding='ISO-8859-1') as f:
            content = f.read()
            f.seek(0,0)
            f.write("Captured Time,Latitude,Longitude,Value,Unit,Location Name,Device ID,MD5Sum,Height,Surface,Radiation,Uploaded Time,Loader ID
    "
    +content)

    このデータセットは、Loader IDとDeviceIDの両方をタグとするユーザタグとして使用しており、コードを走らせてもLoader IDとDevice IDが同じデータの中に同時に存在しないことが判明しているので、Loader IDとDevice IDに基づいてユーザIDとして識別する.まず、Loader IDとDevice IDが同じ場合がある可能性があるので、次のコードで2つのテーブルの下の最大値を求めます.
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    # coding:utf-8
    
    import pandas as pd
    import numpy as np
    
    
    numL = 0
    numD = 0
    for i in range( 135):
        # if(i == 0):
            # continue
        filename = 'measurements-out_'+str(i)+'.csv'
        print(filename)
        data = pd.read_csv(filename, usecols=['Loader ID', 'Captured Time', 'Latitude', 'Longitude','Value', 'Unit', 'Device ID'],encoding='ISO-8859-1')
        # pd.to_numeric(data['Device ID'], errors='coerce').fillna(0)
        order = ['Device ID', 'Captured Time', 'Latitude', 'Longitude','Value', 'Unit']
        data1 = data[order]
        data1['Device ID'] = pd.to_numeric(data1['Device ID'], errors = 'coerce')
         data2.dropna(axis = 0, how = 'any',subset = ['Loader ID','Captured Time','Latitude','Longitude','Value','Unit'], inplace = True)
        if(len(data2['Loader ID']) != 0):
            data2['Loader ID'] = data2['Loader ID'].astype(int)
    
        if(len(data1['Device ID']) != 0):
            D = np.argmax(data1['Device ID'], axis = 1)
        else:
            D = 0
        if(D > numD):
            numD = D
        if(len(data2['Loader ID']) != 0):
            L = np.argmax(data2['Loader ID'], axis = 1)
        else:
            L = 0
        if(L > numD):
            numL = L
        #print("numD = " + str(numD))
    
    print("numL = " + str(numL))
    print("numD = " + str(numD))
    
    

    データ仕上げ
    2つのlabelの最大valueが得られた後、各データセットのデータのフォーマットを変換し、具体的な実行コードを以下に示す.
    # -*- coding:utf-8 -*-
    import pandas as pd
    from datetime import datetime
    from datetime import timedelta
    from timezonefinder import TimezoneFinder
    import numpy as np
    import datetime
    from pytz import timezone
    
    def datetime_as_timezone(date_time, time_zone):
        if(time_zone == None):
            return date_time
        tz = timezone(time_zone)
        utc = timezone('UTC')
        if(time_zone == 'UTC'):
            return date_time
        return date_time.replace(tzinfo=tz).astimezone(utc)
    
    def datetime_to_str(date_time, local):
        date_time_tzone = datetime_as_timezone(date_time, local)
        return '{0:%Y-%m-%d %H:%M:%S}'.format(date_time_tzone)
    
    def clean_data(filenum):
        open_file = '/home/tony/data/measurements-out_' + str(filenum) + '.csv'
        print(open_file)
        #          
        data_sum = pd.read_csv(open_file, usecols=['Loader ID', 'Captured Time', 'Latitude', 'Longitude','Value', 'Unit', 'Device ID'], encoding='ISO-8859-1')
        #       
        order = ['Loader ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Device ID']
        data = data_sum[order]
        #  loader ID   User ID
        data.columns = ['User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Device ID']
        #        
        data['User ID'] = pd.to_numeric(data['User ID'], errors = 'coerce')
        data.dropna(axis = 0, how = 'any',subset = ['User ID','Captured Time','Latitude','Longitude','Value','Unit'], inplace = True)
        #data['User ID']  = data['User ID'].astype(str)
        data['User ID'] = data['User ID'].astype(int)
        #  Loader Id       
        order2 = ['User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit']
        data_user = data[order2]
        #data_user.dropna(axis = 0,how = 'any',  inplace = True)
        # data_user = data_user.dropna(subset = ['User ID'])
        order3 = ['Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Device ID']
        data_device = data_sum[order3]
    # print(data_device)
        #data_device.dropna(axis = 0, how = 'any', subset = ['Device ID'], inplace = True)
        data_device = data_device.dropna(subset = ['Device ID'])
        #  Device ID    User ID
        data_device = data_device.rename(columns={'Device ID':'User ID'})
        data_device['User ID'] = pd.to_numeric(data_device['User ID'], errors = 'coerce')
        data_device.dropna(axis = 0, how = 'any',subset = ['User ID','Captured Time','Latitude','Longitude','Value','Unit'], inplace = True)
        data_device = data_device[order2]
        data_device['User ID'] = data_device['User ID'].astype(int)
        data_device['User ID'] = data_device['User ID'].map(lambda x: (x + 985729))
        #      
        data_user = data_user.append(data_device)
        #     User ID      
        data_user['User ID'] = data_user['User ID'].astype(int)
        #               
        data_user.columns = data_user.columns.str.replace(' ', '_')
        #        Caputered Time     
        #        2011-01-01  2019-10-01     
        data_user[u'Captured_Time'] = pd.to_datetime(data_user[u'Captured_Time'], format='%Y-%m-%d %H:%M:%S',errors='coerce')
        data_user.dropna(inplace = True)
        begin_date = pd.to_datetime('2011-01-01 00:00:00')
        end_date = pd.to_datetime('2018-01-01 00:00:00')
        data_user = data_user[(data_user[u'Captured_Time'] > begin_date)&(data_user[u'Captured_Time'] < end_date)]
        #       cpm  
        data_user = data_user[data_user['Unit'].isin(['cpm'])]
        #   offset        
        data_user['offset'] = None
    
        data_user.columns = ['User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Offset']
        #              
        data_user.to_csv('result.csv', index = False)
        '''
                  
        '''
    
        #         
        data1 = pd.read_csv('result.csv')
        data1 = data1.drop(data1[(data1.Latitude > 36.2) | (data1.Latitude < 34.8) ].index)
        data1 = data1.drop(data1[(data1.Longitude > 139.8) | (data1.Longitude < 138.4) ].index)
        data1['ID'] = range(len(data1))
        order_1 = ['ID','User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Offset']
        data1 = data1[order_1]
        data1.to_csv('Tokyo_'+ str(filenum) +'_.csv', index = False)
        #         
        data2 = pd.read_csv('result.csv')
        data2 = data2.drop(data2[(data2.Latitude > 37.9766) | (data2.Latitude < 36.7981) ].index)
        data2 = data2.drop(data2[(data2.Longitude > 141.053) | (data2.Longitude < 139.157983) ].index)
        data2['ID'] = range(len(data2))
        order_2 = ['ID','User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit', 'Offset']
        data2 = data2[order_2]
        data2.to_csv('Fukushima_'+str(filenum)+'_.csv', index = False)
    
        #     ,           UTC  
        # Find timezone based on longitude and latitude
        tf = TimezoneFinder(in_memory=True)
        data3 = pd.read_csv('result.csv')
        #print(len(data3))
        #                  
        my_func = TimezoneFinder().timezone_at  # Note the no parenthesis on the function call!
        #                
        data3['convert_time'] = None
        #print(data3['Longitude'])
        num = 0
        #              
        if(len(data3) == 0):
            order3 = ['User ID', 'convert_time', 'Latitude', 'Longitude', 'Value', 'Unit']
            data3 = data3[order3]
            data3.columns = ['User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit']
            data3['Offset'] = None
            data3.to_csv('world_'+str(filenum)+'_.csv',index = False)
            return
        local = my_func(lng = data3['Longitude'][0], lat = data3['Latitude'][0])
        print(data3['Longitude'][0], data3['Latitude'][0], local)
        #         
        start = datetime.datetime.now()
        for i in range(len(data3)):
            if (num == 0):
                num = data3['User ID'][i]
                data3['convert_time'][i] = datetime_to_str(datetime.datetime.strptime(data3['Captured Time'][i].split(".")[0],'%Y-%m-%d %H:%M:%S'), local)
            else:
                if(num == data3['User ID'][i]):
                    # print(data3['Longitude'][i], data3['Latitude'][i], local)
                    data3['convert_time'][i] = datetime_to_str(datetime.datetime.strptime(data3['Captured Time'][i].split(".")[0].strip(' \t\r
    '
    ),'%Y-%m-%d %H:%M:%S'), local) else: num = data3['User ID'][i] local = my_func(lng = data3['Longitude'][i], lat = data3['Latitude'][i]) # print(data3['Longitude'][i], data3['Latitude'][i], local) data3['convert_time'][i] = datetime_to_str(datetime.datetime.strptime(data3['Captured Time'][i].split(".")[0].strip(' \t\r
    '
    ),'%Y-%m-%d %H:%M:%S'), local) end = datetime.datetime.now() print((end - start).seconds) order3 = ['User ID', 'convert_time', 'Latitude', 'Longitude', 'Value', 'Unit'] data3 = data3[order3] data3.columns = ['User ID', 'Captured Time', 'Latitude', 'Longitude', 'Value', 'Unit'] data3['Offset'] = None data3.to_csv('world_'+str(filenum)+'_.csv',index = False) if __name__== "__main__": for t in range(0,135): clean_data(t)

    仕上げの過程でpandasライブラリの使用を熟知し,いくつかのライブラリ内部の関数について比較的明確な認識と理解を得た.timezonefinderはpython 3の環境でのみ実行できることに注意してください.