def run(self): #Parametros de los datos #DATE_START = datetime.date(2014,1,1) DATE_START = datetime.date(2020, 1, 1) date_today = datetime.date.today() date_end = datetime.date(date_today.year, date_today.month - 2, 1) #periodo de fechas mensuales dates = pd.period_range(start=str(DATE_START), end=str(date_end), freq='M') for date in dates: self.year = date.year self.month = date.month #hacemos el requerimiento para un chunk del los registros [records, metadata] = funciones_req.peticion_api_info_mensual( self.data_url, self.meta_url, self.month, self.year) db_endpoint = funciones_rds.db_endpoint(self.db_instance_id) funciones_rds.bulkInsert( [(json.dumps(records[i]['fields']), ) for i in range(0, len(records))], [funciones_req.crea_rows_para_metadata(metadata)], self.db_name, self.db_user_name, self.db_user_password, db_endpoint) #Archivo para que Luigi sepa que ya realizo la tarea with self.output().open('w') as out: out.write('Archivo: ' + str(self.year) + ' ' + str(self.month) + '\n')
def __init__(self, fname): #Buscamos el archivo del bucket en la S3 self.data = funciones_s3.abre_file_como_df('dpa20-incidentes-cdmx', 'bucket_incidentes_cdmx/1.preprocesamiento/base_procesada.csv') host = funciones_rds.db_endpoint('db-dpa20') connection = funciones_rds.connect( 'db_incidentes_cdmx', 'postgres', 'passwordDB', host) #cleaned.IncidentesVialesInfoMensual self.dataframe = psql.read_sql("SELECT * FROM {};".format(fname), connection)
def run(self): host = funciones_rds.db_endpoint(self.db_instance_id) yield ExtraeInfoPrimeraVez(self.db_instance_id, self.db_name, self.db_user_name, self.db_user_password, self.subnet_group, self.security_group, host) yield LimpiaInfoPrimeraVez(self.db_instance_id, self.db_name, self.db_user_name, self.db_user_password, self.subnet_group, self.security_group, host) with self.output().open('w') as out_file: out_file.write("Successfully ran pipeline on {}".format(self.date))
def run(self): exito = funciones_rds.create_db_instance( self.db_instance_id, self.db_name, self.db_user_name, self.db_user_password, self.subnet_group, self.security_group) if exito == 1: mins = 7 for i in range(0, 7): time.sleep(60) print("***** Wait...{} min...*****".format(mins - i)) db_endpoint = funciones_rds.db_endpoint(self.db_instance_id) with self.output().open('w') as outfile: outfile.write(str(db_endpoint))
class InsertaMetadatosPruebasUnitariasExtract(CopyToTable): "Inserta los metadatos para las pruebas unitarias en Extract" # Parametros del RDS db_instance_id = 'db-dpa20' subnet_group = 'subnet_gp_dpa20' security_group = 'sg-09b7d6fd6a0daf19a' # Para condectarse a la Base database = 'db_incidentes_cdmx' user = '******' password = '******' host = funciones_rds.db_endpoint(db_instance_id) bucket = 'dpa20-incidentes-cdmx' root_path = 'bucket_incidentes_cdmx' folder_path = '0.pruebas_unitarias' # Nombre de la tabla a insertar table = 'tests.pruebas_unitarias' # Estructura de las columnas que integran la tabla (ver esquema) columns = [("fecha_ejecucion", "VARCHAR"), ("ip_address", "VARCHAR"), ("usuario", "VARCHAR"), ("test", "VARCHAR"), ("test_status", "VARCHAR"), ("level", "VARCHAR"), ("error", "VARCHAR")] def rows(self): #Leemos el df de metadatos for file in ["infile2", "infile3"]: with self.input()[file].open('r') as infile: for line in infile: yield line.strip("\n").split("\t") def requires(self): return { "infile1": CreaTablaPruebasUnitariasMetadatos(self.db_instance_id, self.subnet_group, self.security_group, self.host, self.database, self.user, self.password), "infile2": Test1ForExtract(self.db_instance_id, self.database, self.user, self.password, self.subnet_group, self.security_group, self.host, self.bucket, self.root_path, self.folder_path), "infile3": Test2ForExtract(self.db_instance_id, self.database, self.user, self.password, self.subnet_group, self.security_group, self.host, self.bucket, self.root_path, self.folder_path) }
class TestsForPredicciones(marbles.core.TestCase, mixins.BetweenMixins): """ Clase con pruebas para Predicciones usando marbles: 1.- Probar que la proporcion de etiquetas verdaderas sea "parecida" a las de los datos de entrenamiento 2.- Probar que el numero de columnas del df final es igual al numero de cols del df inicial +3 """ host = funciones_rds.db_endpoint('db-dpa20') connection = funciones_rds.connect( 'db_incidentes_cdmx', 'postgres', 'passwordDB', host) def __init__(self, fname): super(TestsForPredicciones, self).__init__() self.data = funciones_s3.abre_file_como_df('dpa20-incidentes-cdmx', 'bucket_incidentes_cdmx/6.predicciones_prueba/predicciones_modelo.csv') #Con esta FALLA la prueba #self.data = funciones_s3.abre_file_como_df('dpa20-incidentes-cdmx', 'bucket_incidentes_cdmx/2.separacion_base/y_test.csv') self.df_inicial= funciones_s3.abre_file_como_df('dpa20-incidentes-cdmx', 'bucket_incidentes_cdmx/2.separacion_base/X_test.csv') self.df_final = funciones_s3.abre_file_como_df('dpa20-incidentes-cdmx', 'bucket_incidentes_cdmx/{}'.format(fname)) def test_check_porcentaje_1s(self): #Porcentaje de etiquetas verdaderas en las predicciones cursor = self.connection.cursor() cursor.execute("SELECT avg(y_etiqueta)*100 from prediccion.predicciones ; ") porcentaje_1_predicciones = cursor.fetchone() porcentaje_1_predicciones = float(porcentaje_1_predicciones[0]) self.connection.commit() #Porcentaje de verdaderas en los datos porcentaje_1_historicos = self.data.iloc[:,9].mean()*100 #Con esta FALLA la prueba #porcentaje_1_historicos = self.data['target'].mean()*100 try: self.assertBetween(porcentaje_1_predicciones, lower=porcentaje_1_historicos*(0.8), upper=porcentaje_1_historicos*(1.2), msg='El porcentaje de etiquetas verdaderas en las predicciones es muy diferente a la data historica') except marbles.core.marbles.ContextualAssertionError as error: raise ValueError(error) def test_check_num_cols_info_mensual(self): #cols en el df inicial cols_ini = self.df_inicial.columns #cols en el df inicial cols_fin = self.df_final.columns self.assertEqual(len(cols_ini)+4, len(cols_fin), note="El numero de variables en el df de predicciones no coincide con las vars consideradas al inicio")
class AcomodaBase(PostgresQuery): #Para la creacion de la base db_instance_id = 'db-dpa20' db_name = 'db_accidentes_cdmx' db_user_name = 'postgres' db_user_password = '******' subnet_group = 'subnet_gp_dpa20' security_group = 'sg-09b7d6fd6a0daf19a' host = funciones_rds.db_endpoint(db_instance_id) database = db_name user = db_user_name password = db_user_password table = "" # query = "INSERT INTO raw.test SELECT properties -> 'latitud', properties -> 'delegacion_inicio', properties -> 'folio' from raw.incidentesvialesjson limit 10; " query = "CREATE TABLE raw.test2(latitud varchar, delegacion_inicio varchar, folio varchar);" def requires(self): return ExtraeInfoPrimeraVez(self.db_instance_id, self.db_name, self.db_user_name, self.db_user_password, self.subnet_group, self.security_group, self.host)
def run(self): db_endpoint = funciones_rds.db_endpoint(self.db_instance_id) funciones_rds.create_raw_tables(self.db_name, self.db_user_name, self.db_user_password, db_endpoint) self.task_complete = True
class TestsForExtract(marbles.core.TestCase): """ Clase con pruebas de Extract usando marbles: 1.- Probar que el número de meses del periodo coincida con los archivos descargados 2.- Probar que se descargaron todos los registros del periodo """ host = funciones_rds.db_endpoint('db-dpa20') connection = funciones_rds.connect( 'db_incidentes_cdmx', 'postgres', 'passwordDB', host) def test_check_num_archivos(self): #Numero de meses descargados cursor = self.connection.cursor() cursor.execute("SELECT count(*) FROM raw.metadatos") n_descargados = cursor.fetchone() self.connection.commit() #Numero de meses en el periodo date_start = datetime.date(2014,1,1) date_end = datetime.date(2020,3,1) #Para que falle la prueba #date_end = datetime.date.today() dates = pd.period_range(start=str(date_start), end=str(date_end), freq='M') n_periodo = len(dates) self.assertEqual(n_descargados[0], n_periodo, note="El número de meses del período (2014 - fecha) no coincide con el número de meses descargado") def test_check_num_archivos_info_mensual(self): #Numero de meses descargados cursor = self.connection.cursor() cursor.execute("SELECT count(*) FROM raw.metadatos WHERE refine_ano=\'\"2020\"\' and refine_mes=\'\"4\"\';") n_descargados = cursor.fetchone() self.connection.commit() #Para que falle la prueba #n_periodo = 2 n_periodo = 1 self.assertEqual(n_descargados[0], n_periodo, note="El número de meses requerido no coincide con el número de meses descargados") def test_check_num_registros(self): cursor = self.connection.cursor() cursor.execute("SELECT sum(rows) FROM raw.metadatos") n_rows = cursor.fetchall() self.connection.commit() cursor.execute("SELECT count(*) FROM raw.IncidentesVialesJSON") n_reg = cursor.fetchall() self.connection.commit() self.assertEqual(n_rows, n_reg, note="El número de registros extraídos y el número de registros cargados no son iguales") def test_check_num_registros_info_mensual(self): cursor = self.connection.cursor() cursor.execute("SELECT rows FROM raw.metadatos WHERE refine_ano=\'\"2020\"\' and refine_mes=\'\"4\"\';") n_rows = cursor.fetchone() self.connection.commit() cursor.execute("select count(*) from raw.infomensual;") n_reg = cursor.fetchone() self.connection.commit() self.assertEqual(n_rows[0], n_reg[0], note="El número de registros extraídos y el número de registros cargados no son iguales")
def run(self): date_start = datetime.date(self.year, self.month, 1) date_today = datetime.date.today() date_end = datetime.date(date_today.year, date_today.month - 2, 31) hostname = socket.gethostname() ip_address = socket.gethostbyname(hostname) date_time = datetime.datetime.now() # Calcula los meses desde la fecha de inicio hasta dates = pd.period_range(start=str(date_start), end=str(date_end), freq='M') for date in dates: self.year = date.year self.month = date.month self.file = 'incidentes_viales_' self.ext = 'json' #rows = -1 indica todos los registros parameters = { 'rows': -1, 'refine.mes': self.month, 'refine.ano': self.year } #print(parameters) raw = requests.get(self.url, params=parameters) print("******* Estatus ******\n", raw.status_code) print("Ano: ", self.year, "Mes: ", self.month) #En cada ciclo se obtienen algunos parametros para el metadata metadata2 = { 'fecha_ejecucion': date_time.strftime("%d/%m/%Y %H:%M:%S"), 'parametros_url': self.url, #'parametros': parameters, 'ip_address': ip_address, 'usuario': getpass.getuser(), 'nombre_archivo': 'incidentes_viales_{}{}.json'.format(self.month, self.year), 'ruta': 's3://{}/{}/{}/YEAR={}/MONTH={}/'.format( self.bucket, self.root_path, self.etl_path, self.year, self.month), #'tipo_datos': 'json' } # Se especifica que es tipo json y se separan los records de los parametros out = raw.json() records = out['records'] metadata = out['parameters'] # Se juntan toda la metadata (parametros de la tarea + metadata2) # Se normaliza a csv metadata['metadata'] = metadata2 metadata = pd.io.json.json_normalize(metadata).to_string( index=False) def to_upsert(): """ Esta funcion extrae los metadatos que se desean guardar """ return (out['parameters']['dataset'], out['parameters']['timezone'], out['parameters']['rows'], out['parameters']['format'], out['parameters']['refine']['ano'], out['parameters']['refine']['mes'], out['parameters']['metadata']['fecha_ejecucion'], out['parameters']['metadata']['parametros_url'], out['parameters']['metadata']['ip_address'], out['parameters']['metadata']['usuario'], out['parameters']['metadata']['nombre_archivo'], out['parameters']['metadata']['ruta']) # Conexion a la instancia RDS db_endpoint = funciones_rds.db_endpoint(self.db_instance_id) connection = funciones_rds.connect(db_name, db_user_name, db_user_password, db_endpoint) cursor = connection.cursor() # Insertamos la informacion en la tabla raw.metadatos sql = (""" INSERT INTO raw.metadatos(dataset, timezone, rows, format, refine_ano, refine_mes, fecha_ejecucion, parametros_url, ip_address, usuario, nombre_archivo, ruta) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) """) record_to_insert = to_upsert() cursor.execute(sql, record_to_insert) connection.commit() # Cerramos la conexion cursor.close() connection.close() # Guardamos la info en un S3 ses = boto3.session.Session(profile_name='default', region_name='us-east-1') s3_resource = ses.resource('s3') obj = s3_resource.Bucket(self.bucket) # Este es el archivo json with self.output().open('w') as output: #output.write(self.raw.json()) json.dump(records, output) # Se cambian parametros para guardar los metadatos y se guarda el csv self.file = 'metadatos' self.ext = 'csv' with self.output().open('w') as output: output.write(metadata)