Tuve el mismo problema que contaba Jerry en el siguiente enlace al conectar IRIS con el servidor SQL. Mi conexión ODBC está configurada para autenticarse mediante autenticación nativa de Windows.
¿Cómo lo solucioné yo?
Open Database Connectivity (ODBC) es una interfaz de programación de aplicaciones (API) estándar, la cual permite tener acceso a los sistemas que se encargan de administrar las bases de datos.
Tuve el mismo problema que contaba Jerry en el siguiente enlace al conectar IRIS con el servidor SQL. Mi conexión ODBC está configurada para autenticarse mediante autenticación nativa de Windows.
¿Cómo lo solucioné yo?
Estoy escribiendo esta publicación principalmente para recopilar un consenso informal sobre cómo los desarrolladores están utilizando Python junto con IRIS, ¡así que por favor responded a la encuesta al final del artículo! En el cuerpo del artículo, daré un poco de contexto sobre cada una de las opciones proporcionadas, así como sus ventajas, pero si lo preferís, podéis hacer una lectura rápida y simplemente responder la encuesta.
Debido a que la interpretación de SCHEMA por parte de MySQL difiere de la comprensión interpretación común en SQL (como se ve en IRIS, SQL Server u Oracle), nuestro asistente automático de tablas vinculadas puede encontrar errores al intentar recuperar la información de metadatos para construir la tabla vinculada.
(Esto también se aplica a procedimientos y vistas vinculadas)
Al intentar crear una tabla vinculada mediante el asistente, os encontraréis con un error que se parece a esto:
En este tutorial, voy a explicar cómo podéis conectar la plataforma de datos IRIS a una base de datos SQL Server utilizando ODBC.
Prerequisitos:
Hola, espero que este post ayude:
En resumen: MAXLEN es relevante sobre todo para conexiones odbc/jdbc y necesitas especificar un valor apropiado dentro de tus tablas (clases), de lo contrario los datos podrían truncarse cuando los consultes, o incluso fallar cuando intentes insertar datos.
Una larga historia:
Estamos emocionados de seguir lanzando nuevas funciones para InterSystems IRIS Cloud SQL, como la nueva capacidad de Búsqueda Vectorial que se estrenó por primera vez con InterSystems IRIS 2024.1. Cloud SQL es un servicio en la nube que ofrece precisamente eso: acceso SQL en la nube. Esto significa que estaréis usando tecnologías de controladores estándar de la industria como JDBC, ODBC y DB-API para conectaros a este servicio y acceder a vuestros datos. La documentación describe en detalle cómo configurar los ajustes importantes a nivel de controlador, pero no cubre herramientas específicas de terceros, ya que, como podéis imaginar, hay un número infinito de ellas.
En este artículo, complementaremos esa documentación de referencia con pasos más detallados para una popular herramienta de visualización de datos de terceros que varios de nuestros clientes usan para acceder a datos basados en IRIS: Microsoft Power BI.
Hola comunidad,
En esta serie de artículos, exploraremos las siguientes opciones de uso de InterSystems SQL:
Veamos cómo crear de forma sencilla una conexión ODBC a IRIS en Windows para principiantes :D, probar la conexión y extraer datos en Excel.
Excel puede conectarse a bases de datos externas a través de ODBC. Dado que IRIS habla ODBC, podemos aprovechar el InterSystems ODBC Driver para crear una conexión ODBC con IRIS que Excel puede utilizar.
Recientemente, mientras discutía con mis alumnos el acceso a los datos almacenados en IRIS desde diferentes lenguajes, surgió la pregunta de si era posible iniciar la conexión y obtener datos de la solución Cloud (InterSystems IRIS CloudSQL) desde Microsoft Excel, y no al revés. Teniendo en cuenta las muchas y variadas formas en las que uno puede obtener datos en Excel (importar datos de fuentes externas, conectarse a bases de datos utilizando drivers ODBC, utilizando power queries y web queries, etc.) la opción obvia era probar con el driver ODBC. La única tarea que quedaba era tratar de conectarse a la base de datos en la nube utilizando el driver ODBC.
.png)
Este artículo tiene la intención de ser un sencillo tutorial de cómo crear conexiones ODBC y trabajar con ellas, ya que me pareció que empezar con ellas es un poco confuso. Yo tuve la ayuda de unas personas increíbles, y creo que todos merecemos ese apoyo.
Voy dividir cada pequeña parte en sesiones, así que puedes ir directamente a la que necesites, aunque recomiendo leerlo todo.
Voy a usar los datos de ejemplo creados en un artículo previo, Tutorial rápido para crear bases de datos de ejemplo: Samples.PersistentData, con las propiedades Name y Age.
Sigue estos sencillos y rápidos pasos para configurar las conexionesODBC/JDBC con InterSystems IRIS® e InterSystems IRIS for Health™:
Ahora en un sencillo formato de lista para ayudarte a realizar el proceso en tu propio sistema.
¡Esperamos que os resulte útil!
Últimamente me han preguntado en varias ocasiones cómo hacer que el Framework Laravel funcione con InterSystems IRIS Data Platform. Ha pasado un tiempo desde la publicación de este anuncio sobre Laravel e InterSystems Caché. En este artículo mostraremos unas breves instrucciones sobre cómo configurar un proyecto Laravel para usarlo con InterSystems IRIS a través de ODBC.
¿Qué es Laravel?
Una de nuestras apps utiliza una consulta de clase para un informe ZEN y funciona perfectamente en ese informe, produciendo los resultados esperados. Hemos migrado a InterSystems Reports y nos hemos dado cuenta de que, para un informe que utiliza la misma consulta de clase, aparecen en la parte de abajo más de 100 filas extra con los mismos valores en las columnas.
Descartamos InterSystems Reports como fuente del problema reproduciendo el problema de "filas extra" con una hoja de cálculo de Excel que llama a la misma consulta de clase utilizando un procedimiento almacenado.
¿Cuál era el problema? Cuando llamábamos al procedimiento almacenado desde el antiguo ZEN Report o desde la función SQL Query en el Portal de Administración, no veíamos estas filas adicionales.
En mis artículos anteriores, mostré los pasos para conectar, recuperar y guardar datos en Caché desde Appeon PowerBuilder usando ODBC.
En este artículo, mostraré cómo eliminar datos de Caché con Appeon PowerBuilder (https://www.appeon.com/products/powerbuilder) usando ODBC..png)
Estoy usando Company.cls de Samples-Data (https://github.com/intersystems/Samples-Data/tree/master/cls/Sample)
¡Empecemos!
Paso 1:En primer lugar, debemos establecer una conexión (https://community.intersystems.com/post/connecting-cach%C3%A9-appeon-powerbuilder-using-odbc)
En mi artículo anterior, expliqué los pasos para conectarse a Caché desde Appeon PowerBuilder usando ODBC.
En este artículo, mostraré cómo recuperar datos de Caché con Appeon PowerBuilder (https://www.appeon.com/products/powerbuilder) utilizando ODBC..png)
Siguiendo el ejemplo disponible en GitHub FHIR IntegratedML vamos usar el modelo resumido para entrenar el modelo de predicción de "No Asistirá" (NotShow).
Haremos un match entre los campos de la tabla PackageSample.NoShowMLRow y los campos de TrakCare. El punto de partida en TrakCare será la tabla SQLUser.RB_Appointment.
| CAMPO | TRAKCARE | OBSERVACIONES |
|---|---|---|
| Gender | APPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_Gender | Se espera valores "F" y "M" |
| ScheduledWeekDay | {fn DAYOFWEEK(APPT_DateComp) } | Días de la semana Domingo (1) a Sábado (7) |
| ScheduledWeek | {fn WEEK(APPT_DateComp)} | El número de la semana (1 a 52) |
| WaitingDays | DATEDIFF('dd',APPT_BookedDate, APPT_DateComp) | Días entre el agendamiento y la fecha del compromiso) |
| Age | DATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp) | Edad del paciente (en años) al día de la cita. |
| Hypertension | CIE10: (I10-I15) Enfermedades hipertensivas | |
| Diabetes | CIE10: (E10-E14) Diabetes mellitus | |
| Alcoholism | CIE10: (F10) Trastornos mentales y de comportamiento debidos al consumo de alcohol | |
| Handicap | CIE10: (Z73.6) Problemas relacionados con la limitación de las actividades debido a discapacidad | |
| SMSreceived | APPT_Confirmation | Si no tenemos sistema de envío de mensajes, usaremos el campo "Confirmado" |
| Noshow | APPT_Status | Usaremos el estado de cita para saber si el paciente fue atendido o se presentó al menos al compromiso |
Para traer los datos desde TrakCare, vamos a preparar la consulta, y teniendo en cuenta los campos que se requieren, la query quedaría así:
Select
APPT_PAPMI_DR->PAPMI_PAPER_DR PatientID,
APPT_RowId ApptID,
APPT_DateComp ApptDate,
APPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_Gender Gender,
{fn DAYOFWEEK(APPT_DateComp)} ScheduledWeekDay,
{fn WEEK(APPT_DateComp)} ScheduledWeek,
DATEDIFF('dd',APPT_BookedDate, APPT_DateComp) WaitingDays,
DATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp) Age,
CASE APPT_Confirmation
WHEN 'Y' THEN 1
ELSE 0
END SMSreceived,
CASE APPT_Status
WHEN 'P' THEN 1
WHEN 'A' THEN 0
WHEN 'X' THEN 0
WHEN 'I' THEN 0
WHEN 'N' THEN 1
WHEN 'T' THEN 0
WHEN 'H' THEN 0
WHEN 'C' THEN 0
WHEN 'S' THEN 0
WHEN 'D' THEN 0
ELSE APPT_Status
END Noshow
from RB_Appointment
Se puede modificar para traer todos los registros o filtrar por ejemplo el año en curso (dejar al menos fuera las citas futuras, pues estas servirán posteriormente, una vez entrenado el modelo para predecir el comportamiento de citas futuras. Se puede igualmente filtrar por establecimiento (APPT_AS_ParRef->AS_RES_ParRef->RES_CTLOC_DR->CTLOC_HOSPITAL_DR) pues es posible que el comportamiento sea diferente dependiendo esta variable (por cercanía al centro de atención por ejemplo).
Nota: Considerar si excluir del análsis citas canceladas (X) u otros estados como Transferido (T) pues son citas que se mostrarán como "NoShow" pero no se puede atribuir eso a un comportamiento del paciente necesariamente. Para este ejemplo se han considerado, pero a valor "0", es decir NoShow = False.
import pandas as pd
import jaydebeapi as jdbc
import time
import pyodbc as odbc
import irisnative
Tendremos funciones para determinar si el paciente está diagnosticado con Huipertensión, Diabetes, Alcoholismo o alguna restricción física (invalidez).
La función recibirá un arreglo con los diagnósticos del paciente al momento de la cita (filtrados por fecha) para retornar un 0 (False) o un 1 (True). Basta con que uno de los diagnósticos sea HTA para saber que el paciente en ese momento es hipertenso.
def is_hta (dxlist):
ishta = 0
htalist = ('I10', 'I11','I12', 'I13', 'I14', 'I15')
for i in dxlist:
if i in htalist:
ishta = 1
return ishta
def is_dbt (dxlist):
isdbt = 0
dbtlist = ('E10', 'E11','E12', 'E13', 'I14')
for i in dxlist:
if i in dbtlist:
isdbt = 1
return isdbt
def is_disabilited (dxlist):
isdisabilited = 0
disabilitedlist = ('Z73.6','1')
for i in dxlist:
if i in disabilitedlist:
isdisabilited = 1
return isdisabilited
def is_alcoholism (dxlist):
isalcoholism = 0
alcoholismlist = ('F10','1')
for i in dxlist:
if i in alcoholismlist:
isalcoholism = 1
return isalcoholism
def listdxbypatid (patid):
listadxsql = ()
if patid:
idpaciente = patid
sqlpatdx = """
select %nolock
MR_DIAGNOS.MRDIA_ICDCode_DR->MRCID_Code,
MR_DIAGNOS.MRDIA_DATE
from SQLUser.MR_ADM, SQLUser.MR_DIAGNOS
where MR_ADM.MRADM_RowId IN (SELECT PAADM_MainMRADM_DR
FROM PA_Adm
WHERE PAADM_PAPMI_DR = """ + str(idpaciente) + """ )
and MR_ADM.MRADM_RowId = MR_DIAGNOS.MRDIA_MRADM_ParRef
"""
listadxsql = pd.read_sql(sqlpatdx, conn)
return listadxsql
Preparamos la conexión utilizando la librería jaydebeapi y el conector que corresponde al ambiente a utilizar. En este caso, se trata de un ambiente sobre HealthShare, por lo que usaremos el JDBC de Cache.
# Establecemos nuestras variables de conexión (host, port, namespace)
envhost = "localhost"
envport = 1983
envns = "TRAK"
dbuser = "superuser"
dbaccess = "SYS"
url = "jdbc:Cache://" + envhost + ":" + str(envport) + "/" + envns
driver = 'com.intersys.jdbc.CacheDriver'
irisdriver = 'com.intersystems.jdbc.IRISDriver'
user = dbuser
password = dbaccess
# Para este ejemplo, el jar para Cache se encuentra bajo la carpeta "resources"
# ruta relativa a la ubicación de este notebook
#jarfile = "resources/cachejdbc.jar"
jarfile = "/Users/ArielArias/cachejdbc.jar"
conn = jdbc.connect(driver, url, [user, password], jarfile)
curs = conn.cursor()
Asignamos la consulta en una variable, para poder modificar posteriormente si es necesario. De esta forma además podemos utilizar asignación en múltiples líneas para tener una mejor vosión de lo que estamos extrayendo desde TrakCare.
sql_str = """Select TOP 3500
APPT_PAPMI_DR->PAPMI_PAPER_DR PatientID,
APPT_RowId ApptID,
APPT_DateComp ApptDate,
APPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_Gender Gender,
{fn DAYOFWEEK(APPT_DateComp)} ScheduledWeekDay,
{fn WEEK(APPT_DateComp)} ScheduledWeek,
DATEDIFF('dd',APPT_BookedDate, APPT_DateComp) WaitingDays,
DATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp) Age,
CASE APPT_Confirmation
WHEN 'Y' THEN 1
ELSE 0
END SMSreceived,
CASE APPT_Status
WHEN 'P' THEN 1
WHEN 'A' THEN 0
WHEN 'X' THEN 0
WHEN 'I' THEN 0
WHEN 'N' THEN 1
WHEN 'T' THEN 0
WHEN 'H' THEN 0
WHEN 'C' THEN 0
WHEN 'S' THEN 0
WHEN 'D' THEN 0
ELSE APPT_Status
END Noshow
from RB_Appointment
Where
APPT_DateComp BETWEEN to_date('01/01/2021','dd/mm/yyyy') AND NOW()
AND APPT_AS_ParRef->AS_RES_ParRef->RES_CTLOC_DR->CTLOC_HOSPITAL_DR IN (12129)"""
Utilizando la librerías pandas ejecutamos la consulta SQL y la dejamos en un DataFrame para posterior manipulación. Nos falta aún las columnas relacionadas a diagnósticos del paciente a la fecha de la cita (por ahora no consideraremos TODOS los diagnósticos del paciente, sólo los confirmados y que fueron ingresados previo a la fecha del compromiso.
start = time.time()
data = pd.read_sql(sql_str, conn)
end = time.time()
elapsedtime = end - start
# Sólo para tener una referencia veremos el tiempo de ejecución de la consulta
# Esto ayudará a evaluar cuántos registros se puede procesar
# O planificar una ejecución por períodos de tiempo más reducidos
print("Tiempo de Ejecución SQL: ",int(elapsedtime), " Segundos")
# Agregamos las columnas de Dx; con valores negativos por ahora
data["Hypertension"] = 0
data["Diabetes"] = 0
data["Alcoholism"] = 0
data["Handicap"] = 0
# Verificamos nuestro dataframe
data.head()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| PatientID | ApptID | ApptDate | Gender | ScheduledWeekDay | ScheduledWeek | WaitingDays | Age | SMSreceived | Noshow | Hypertension | Diabetes | Alcoholism | Handicap | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 598205 | 11683||11250||1 | 2021-01-21 | F | 5 | 4 | 0 | 27 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 598205 | 11683||11804||1 | 2021-01-28 | F | 5 | 5 | 1 | 27 | 0 | 1 | 0 | 0 | 0 | 0 |
| 2 | 598205 | 11683||13466||1 | 2021-02-18 | F | 5 | 8 | 0 | 27 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 598205 | 11683||15128||1 | 2021-03-11 | F | 5 | 11 | 0 | 27 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 598205 | 11683||15682||1 | 2021-03-18 | F | 5 | 12 | 0 | 27 | 0 | 0 | 0 | 0 | 0 | 0 |
Recorremos el Arreglo y traemos la lista de diagnósticos para cada paciente. Para optimizar el tiempo, verificamos si ya tenemos los diagnósticos del paciente teniendo una lista con los PatientID
start = time.time()
patient = []
## is_hta
## is_dbt
## is_disabilited
## is_alcoholism
for index, row in data.iterrows():
if row['PatientID'] not in patient:
patient.append(row['PatientID'])
patappt = (row['ApptID'], row['PatientID'], row['ApptDate'])
listpatdx = listdxbypatid(row['PatientID'])
# Ya tenemos los diagnósticos del Paciente;
# ahora filtramos sólo los previos a la cita y los dejamos en una lista:
if len(listpatdx):
low_apptdate = listpatdx[listpatdx["MRDIA_Date"] <= patappt[2]]
if len(low_apptdate):
# Ahora necesitamos saber si el paciente "ES" o "ERA" Hipertenso para la fecha de la cita:
diaghta = is_hta(low_apptdate.MRCID_Code)
diagdbt = is_dbt(low_apptdate.MRCID_Code)
diagdis = is_disabilited(low_apptdate.MRCID_Code)
diagalcohol = is_alcoholism(low_apptdate.MRCID_Code)
else:
diaghta = 0
diagdbt = 0
diagdis = 0
else:
diaghta = 0
diagdbt = 0
diagdis = 0
# Modificamos la información en la fila correspondiente
# Sabemos que por ApptID habrá sólo un registro:
data.loc[data.ApptID == row['ApptID'],'Hypertension'] = diaghta
data.loc[data.ApptID == row['ApptID'],'Diabetes'] = diagdbt
data.loc[data.ApptID == row['ApptID'],'Handicap'] = diagdis
data.loc[data.ApptID == row['ApptID'],'Alcoholism'] = diagalcohol
end = time.time()
print(end - start)
Cerramos la conexión, de momento no la usaremos.
conn.close()
En este ejemplo, no podemos usar el mismo servidor pues en su versión no incluye la función de ML; así es que usaremos una instancia con IRIS for Health que incorpora ML.
Dado que la librería de python jaydebeapi soporta sólo un dirver conexión por ejecución, no podemos usar el mismo método pues habrá un error al intentar usarla para conectar IRIS (posterior a conectar Caché).
Para seguir con el ejemplo y no perder el DataFrame obtenido, vamos a crear una conexión a IRIS utilizando ODBC
Usaremos la misma instancia del ejemplo que hemos usado hasta ahora, es decir el NameSpace FHIRSERVER
dsn = 'IRIS FHIRML'
server = 'localhost' #IRIS server container or the docker machine's IP
port = '32782' # or 8091 if docker machine IP is used
database = 'FHIRSERVER'
username = 'SUPERUSER'
password = 'SYS'
irisconn = odbc.connect('DSN='+dsn+';')
irisconn.setencoding(encoding='utf-8')
iriscurs = irisconn.cursor()
modelName = "TrakNoShow"
fhirsql = """Select
Age, Alcoholism, Diabetes,
Gender, Handicap, Hypertension,
Noshow, SMSreceived, ScheduledWeek,
ScheduledWeekDay, WaitingDays
FROM PackageSample.""" + modelName + "MLRow"
# Copiamos la tabla NoShowMLRow a nuestra TrakNoShowMLRow:
sqlcreate = "CREATE TABLE PackageSample." + modelName + "MLRow ("
sqlcreate = sqlcreate + "Gender CHAR(30),"
sqlcreate = sqlcreate + "ScheduledWeekDay INT,"
sqlcreate = sqlcreate + "ScheduledWeek INT,"
sqlcreate = sqlcreate + "WaitingDays INT,"
sqlcreate = sqlcreate + "Age INT,"
sqlcreate = sqlcreate + "Hypertension BIT,"
sqlcreate = sqlcreate + "Diabetes BIT,"
sqlcreate = sqlcreate + "Alcoholism BIT,"
sqlcreate = sqlcreate + "Handicap BIT,"
sqlcreate = sqlcreate + "SMSreceived BIT,"
sqlcreate = sqlcreate + "Noshow BIT)"
Ejecutamos la creción de la tabla:
iriscurs.execute(sqlcreate)
iriscurs.commit()
Para hacer una inserción directa de los datos, haremos una copia del DataFrame para eliminar luego algunas columnas que no usaremos de momento; esto sólo para hacer un INSERT más directo al momento de recorrer el DataFrame.
sqltest = "INSERT INTO PackageSample." + modelName + "MLRow"
sqltest = sqltest + " (Gender,ScheduledWeekDay,ScheduledWeek,WaitingDays,"
sqltest = sqltest + "Age,SMSreceived,Noshow,Hypertension,Diabetes,Alcoholism,Handicap) "
sqltest = sqltest + "values(?,?,?,?,?,?,?,?,?,?,?)"
for index, row in data.iterrows():
params = [[row.Gender,row.ScheduledWeekDay,row.ScheduledWeek,row.WaitingDays,row.Age,row.SMSreceived,row.Noshow,row.Hypertension,row.Diabetes,row.Alcoholism,row.Handicap]]
iriscurs.executemany(sqltest,params)
iriscurs.commit()
Para efecto de visualización, vamos a trabajar con variables para nombrar nuestro modelo, y definir con cuántos datos vamos a entrenar y cuántos vamos a utilizar para validar.
datasize = len(irisdata)
modelName = "TrakNoShow"
predictingCol = "Noshow"
# si requiere reiniciar el modelo, se elimina las tablas creadas:
sqldropcross = "DROP TABLE PackageSample." + modelName + "MLRowCrossValidation"
sqldroptest = "DROP TABLE PackageSample." + modelName + "MLRowTest"
sqldroptrain = "DROP TABLE PackageSample." + modelName + "MLRowTraining"
sqldropval = "DROP TABLE PackageSample." + modelName + "MLRowValidation"
sqldropmodel = "DROP MODEL " + modelName + "Model"
# definimos con qué porcentaje de los datos realizaremos el crossvalidation:
cvLen = int(datasize * 0.9)
# Y el resto para testing:
testLen = datasize - cvLen
# tamaño de los datos para entrenamiento:
trainLen = int(cvLen * 0.75)
validationLen = cvLen - trainLen
# Crearemos modelo con CrossValidation:
sqlcrossval = "CREATE TABLE PackageSample." + modelName + "MLRowCrossValidation AS "
sqlcrossval = sqlcrossval + "SELECT * FROM PackageSample." + modelName + "MLRow WHERE Id IN ("
sqlcrossval = sqlcrossval + "SELECT TOP " + str(cvLen) + " idx "
sqlcrossval = sqlcrossval + "FROM community.randrange(1, " + str(datasize+1) + ") "
sqlcrossval = sqlcrossval + "ORDER BY randValue)"
# Creamos la tabla para pruebas del modelo
sqltest = "CREATE TABLE PackageSample." + modelName + "MLRowTest AS "
sqltest = sqltest + "SELECT TOP " + str(testLen) + " * FROM PackageSample." + modelName + "MLRow WHERE Id NOT IN ("
sqltest = sqltest + "SELECT Id FROM PackageSample." + modelName + "MLRowCrossValidation)"
# Creamos tabla para entrenamiento:
sqltrain = "CREATE TABLE PackageSample." + modelName + "MLRowTraining AS "
sqltrain = sqltrain + "SELECT * FROM PackageSample." + modelName + "MLRowCrossValidation WHERE Id IN ("
sqltrain = sqltrain + "SELECT TOP " + str(trainLen) + " idx "
sqltrain = sqltrain + "FROM community.randrange(1, " + str(datasize+1) + ") "
sqltrain = sqltrain + "ORDER BY randValue)"
# Tabla para validación:
sqlval = "CREATE TABLE PackageSample." + modelName + "MLRowValidation AS "
sqlval = sqlval + "SELECT TOP " + str(validationLen) + " * "
sqlval = sqlval + "FROM PackageSample." + modelName + "MLRowCrossValidation "
sqlval = sqlval + "WHERE Id NOT IN ("
sqlval = sqlval + "SELECT Id FROM PackageSample." + modelName + "MLRowTraining)"
# Para creación del modelo:
sqlcreatemodel = "CREATE MODEL "+ modelName + "Model PREDICTING (" + predictingCol + ") "
sqlcreatemodel = sqlcreatemodel + "FROM PackageSample." + modelName + "MLRowTraining"
# Para entrenar modelo:
sqltrainmodel = 'TRAIN MODEL ' + modelName + 'Model USING {"seed": 1}'
# Para validar modelo:
sqlvalmodel = "VALIDATE MODEL " + modelName + "Model FROM PackageSample." + modelName + "MLRowValidation"
Podemos ejecutar una a una las sentencias desde nuestro notebook para crear el modelo, y luego entrenarlo.
# Creamos tabla CrossValidation:
iriscurs.execute(sqlcrossval)
iriscurs.commit()
# Creamos tabla Test:
iriscurs.execute(sqltest)
iriscurs.commit()
# Creamos tabla para entrenamiento:
iriscurs.execute(sqltrain)
iriscurs.commit()
# Creamos tabla para validacion:
iriscurs.execute(sqlval)
iriscurs.commit()
# Creamos el modelo:
iriscurs.execute(sqlcreatemodel)
iriscurs.commit()
# Entrenamos el modelo:
iriscurs.execute(sqltrainmodel)
iriscurs.commit()
# Validamos el modelo:
iriscurs.execute(sqlvalmodel)
iriscurs.commit()
Entrenado el modelo, podemos utilizarlo para conocer la predicción, ya sea que enviamos datos desde otro origen o podemos utilizar consultas directamente sobre el modelo. Un ejemplo:
# TrakNoShowModel
# Probar consultas hacia el modelo:
sqlpredict = "SELECT top 10 PREDICT(TrakNoShowModel) AS PredictedNoshow, Noshow AS ActualNoshow FROM PackageSample.TrakNoShowMLRowTest"
predictdata = pd.read_sql(sqlpredict, irisconn)
predictdata
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| PredictedNoshow | ActualNoshow | |
|---|---|---|
| 0 | False | False |
| 1 | True | True |
| 2 | False | False |
| 3 | False | False |
| 4 | False | False |
| 5 | False | False |
| 6 | False | False |
| 7 | False | False |
| 8 | False | False |
| 9 | True | False |
Durante la preparación de este documento se debió ajustar algunos parámetros y consultas para poder terminarlo. Se detalla a continuación para posible solución al replicar los pasos en otro ambiente:
Algunas mejoras a la aplicación de este ejemplo, y que pueden estar disponible en nuevos post:
Se puede trabajar estos mismos pasos, direcamente desde IRIS, aprovechando aún más sus propiedades y facilidad para acceder a los datos. Se hizo como notebook sólo para ejemplificar que se puede traer varios origenes de datos a IRIS para crear un modelo de Machine Learning, entrenarlo, y validarlo.
Tener estos pasos en una clase de IRIS, permitirá además operativizar el modelo, por medio de webservice como el ejemplo disponible en readmision demo
Contar con una carga programada desde el origen que permita incluso actualizar datos, por ejemplo, del estado de cita. Esto permitirá por ejemplo, construir un cubo y posterior cuadro de mando que permita identificar a los pacientes con alta posibilidad de no asistir para reforzar el contacto.
https://www.appeon.com/products/powerbuilder
Appeon PowerBuilder es una herramienta de desarrollo empresarial que permite crear componentes y aplicaciones empresariales basadas en datos.
Es un producto de una suite de Appeon que ofrece las herramientas para desarrollar aplicaciones cliente/servidor, web, móviles y distribuidas.
En este artículo, mostraré los pasos para conectarse a Caché con Appeon PowerBuilder usando ODBC.
Paso 1 : Asegúrate de que la opción "ODBC Driver" está seleccionada al instalar IRIS:.png)
Este es un ejemplo de código que funciona en IRIS 2020.1 y en Caché 2018.1.3
No se mantendrá sincronizado con las nuevas versiones.
Y NO cuenta con el servicio de soporte de InterSystems.Palabras clave: Python, JDBC, SQL, IRIS, Jupyter Notebook, Pandas, Numpy y aprendizaje automático
Hoy me he encontrado con este artículo de Zphong Li, que publicó en Enero de 2020 pero que creo que es muy interesante y aún útil a día de hoy. Así que... para los que estéis haciendo vuestros primeros pinitos en Machine Learning con InterSystems IRIS, Python y Jupyter... aquí lo tenéis!!
Esta es una nota sencilla de 5 minutos, donde os muestro cómo invocar el controlador JDBC de IRIS con la ayuda de Python 3, por ejemplo desde un Jupyter Notebook, para leer y escribir datos en una instancia de la base de datos de IRIS vía SQL.
El año pasado Zhong Li publicó una nota breve sobre como Enlazar Python con una base de datos Caché (sección 4.7). Ahora podría ser el momento de recapitular algunas opciones y discusiones sobre el uso de Python para acceder a una base de datos de IRIS, para leer sus datos en un dataframe de Pandas y una matriz de NumPy para realizar un análisis básico, y después escribir algunos datos pre-procesados o normalizados de nuevo en IRIS y que esté listo para canalizaciones (pipelines) adicionales de ML/DL.
Inmediatamente se me ocurren varias opciones:
¿Hay alguna otra opción que se me haya escapado? También estoy interesado en probarla.
¿Comenzamos con un enfoque JDBC común? En la siguiente nota breve recapitularemos ODBC, Spark y la API nativa de Python.
Los siguientes componentes comunes se abordan en esta demostración rápida:
En esta nota rápida NO se abordarán los siguientes aspectos - son importantes y pueden tratarse por separado con soluciones, implementaciones y servicios específicos:
Simplemente ejecuté un contenedor IRIS 2019.4 como servidor "remoto" de la base de datos. Puedes utilizar cualquier instancia de IRIS a la que tengas acceso autorizado.
zhongli@UKM5530ZHONGLI MINGW64 /c/Program Files/Docker Toolbox
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d86be69a03ab quickml-demo "/iris-main" 3 days ago Up 3 days (healthy) 0.0.0.0:9091->51773/tcp, 0.0.0.0:9092->52773/tcp quickml
Reutilizaremos el mismo enfoque de configuración descrito aquí para Anaconda (sección 4.1) y aquí para Jupyter Notebook (sección 4) en un ordenador portátil. Python 3.x se instala junto con este paso.
!conda install --yes -c conda-forge jaydebeapiJayDeBeApi utiliza JPype 0.7 en el momento de escribir este artículo (enero del 2020), pero no funciona debido a un error conocido, por lo que tuve que utilizar la 0.6.3
!conda install --yes -c conda-forge JPype1=0.6.3 --force-reinstallHay una documentación oficial de JDBC en IRIS aquí.
Para las ejecuciones de Python SQL sobre JDBC, utilicé los siguientes códigos como ejemplo. Se conecta a una tabla de datos llamada "DataMining.IrisDataset" dentro del namespace "USER" de esta instancia de IRIS.
### 1. Establezca las variables de entorno, si es necesario
#importa os
#os.environ['JAVA_HOME']='C:\Progra~1\Java\jdk1.8.0_241'
#os.environ['CLASSPATH'] = 'C:\interSystems\IRIS20194\dev\java\lib\JDK18\intersystems-jdbc-3.0.0.jar'
#os.environ['HADOOP_HOME']='C:\hadoop\bin'
#winutil binary must be in Hadoop's Home
### 2. Obtiene la conexión JDBC y el cursor
import JayDeBeApi
url = "jdbc:IRIS://192.168.99.101:9091/USER"
driver = 'com.intersystems.jdbc.IRISDriver'
user = "SUPERUSER"
password = "SYS"
#libx = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18"
jarfile = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18/intersystems-jdbc-3.0.0.jar"
conn = jaydebeapi.connect(driver, url, [user, password], jarfile)
curs = conn.cursor()
### 3. Especifica la fuente de la tabla de datos
dataTable = "DataMining.IrisDataset"
### 4. Obtiene el resultado y visualiza
curs.execute("select TOP 20 * from %s" % dataTable)
result = curs.fetchall()
print("Total records: " + str(len(result)))
for i in range(len(result)):
print(result[i])
### 5. Cerrar y limpiar - Los mantendre abiertos para los próximos accesos.
#curs.close()
#conn.close()
Total records: 150 (1, 1.4, 0.2, 5.1, 3.5, 'Iris-setosa') (2, 1.4, 0.2, 4.9, 3.0, 'Iris-setosa') (3, 1.3, 0.2, 4.7, 3.2, 'Iris-setosa') ... ... (49, 1.5, 0.2, 5.3, 3.7, 'Iris-setosa') (50, 1.4, 0.2, 5.0, 3.3, 'Iris-setosa') (51, 4.7, 1.4, 7.0, 3.2, 'Iris-versicolor') ... ... (145, 5.7, 2.5, 6.7, 3.3, 'Iris-virginica') ... ... (148, 5.2, 2.0, 6.5, 3.0, 'Iris-virginica') (149, 5.4, 2.3, 6.2, 3.4, 'Iris-virginica') (150, 5.1, 1.8, 5.9, 3.0, 'Iris-virginica')
Ahora hemos verificado que Python en JDBC estaba funcionando. Lo siguiente es solo un poco de análisis de datos de rutina y preprocesamiento para los canales habituales de ML que deberíamos mencionar una y otra vez para demostraciones y comparaciones posteriores, por lo que se adjunta para mayor comodidad.
Instala los paquetes Pandas y NumPy a través de Conda si aún no están instalados, como se explicó en el punto 3.3.
A continuación, ejecute lo siguiente como un ejemplo:
### Transforma los resultados de SQL "sqlData" en un dataframe de Pandas "df", y después en una matriz de NumPy "arrayN" para otras canalizaciones (*pipelines*) de ML
import pandas as pd
sqlData = "SELECT * from DataMining.IrisDataset"
df= pd.io.sql.read_sql(sqlData, conn)
df = df.drop('ID', 1)
df = df[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']]
# Establece las etiquetas en 0, 1, 2, para la matriz NumPy
df.replace('Iris-setosa', 0, inplace=True)
df.replace('Iris-versicolor', 1, inplace=True)
df.replace('Iris-virginica', 2, inplace=True)
# Convierte el dataframe en una matriz Numpy
arrayN = df.to_numpy()
### 6. Cierra y limpia - ¿si la conexión ya no es necesaria?
#curs.close()
#conn.close()
Echemos un vistazo rutinario a los datos actuales:
df.head(5)

df.describe()

Ahora tenemos un DataFrame, y una matriz NumPy normalizada de una tabla de datos fuente a nuestra disposición.
Ciertamente, ¿podemos probar varios análisis de rutina con los que comenzaría un experto en ML, como se indica a continuación, en Python para reemplazar a R, como en el enlace que se encuentra aquí?

La fuente de datos se cita aquí
Ciertamente, podemos dividir los datos en un conjunto de Entrenamiento y otro de Validación o Prueba, como es habitual, y después escribirlos de nuevo en tablas temporales de la base de datos, para algunas emocionantes funciones ML de IRIS:
import numpy as np
from matplotlib
import pyplot
from sklearn.model_selection import train_test_split
# mantiene, por ejemplo, el 20% = 30 filas como datos de prueba, y el 80% = 120 filas para entrenamiento
X = arrayN[:,0:4]
y = arrayN[:,4]
X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1, shuffle=True)
# Hace que el 80% de las filas, escogidas aleatoriamente, estén en el conjunto Entrenamiento
labels1 = np.reshape(Y_train,(120,1))
train = np.concatenate([X_train, labels1],axis=-1)
# Hace que el 20% de las filas, escogidas eleatoriamente, estén en el conjunto Prueba,
lTest1 = np.reshape(Y_validation,(30,1))
test = np.concatenate([X_validation, lTest1],axis=-1)
# Escribe el conjunto de datos de entrenamiento en un dataframe de Pandas
dfTrain = pd.DataFrame({'SepalLength':train[:, 0], 'SepalWidth':train[:, 1], 'PetalLength':train[:, 2], 'PetalWidth':train[:, 3], 'Species':train[:, 4]})
dfTrain['Species'].replace(0, 'Iris-setosa', inplace=True)
dfTrain['Species'].replace(1, 'Iris-versicolor', inplace=True)
dfTrain['Species'].replace(2, 'Iris-virginica', inplace=True)
# Escribe los datos de pruebas en un dataframe de Pandas
dfTest = pd.DataFrame({'SepalLength':test[:, 0], 'SepalWidth':test[:, 1], 'PetalLength':test[:, 2], 'PetalWidth':test[:, 3], 'Species':test[:, 4]})
dfTest['Species'].replace(0, 'Iris-setosa', inplace=True)
dfTest['Species'].replace(1, 'Iris-versicolor', inplace=True)
dfTest['Species'].replace(2, 'Iris-virginica', inplace=True)
### 3. Especifica los nombres de las tablas temporales
dtTrain = "TRAIN02"
dtTest = "TEST02"
### 4. Crea 2 tablas temporales - puedes probar eliminar las tablas temporales y volver a crearlas una y otra vez
curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" %(dtTrain,dfTrain.columns[0],dfTrain.columns[1],dfTrain.columns[2], dfTrain.columns[3], dfTrain.columns[4]))
curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" %(dtTest,dfTest.columns[0],dfTest.columns[1],dfTest.columns[2],dfTest.columns[3],dfTest.columns[4]))
### 5. Escribe el conjunto de Entrenamiento y el conjunto de Prueba en las tablas. Se puede intentar borrar cada vez el registro anterior y luego insertarlo otra vez.
curs.fast_executemany = True
curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTrain, list(dfTrain.itertuples(index=False, name=None)) )
curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTest, list(dfTest.itertuples(index=False, name=None)) )
### 6. Cierra y limpia - ¿si la conexión ya no es necesaria?
#curs.close()
#conn.close()
Ahora, si cambiamos a la Consola de Administración de IRIS, o a la Consola del Terminal SQL, deberíamos ver 2 tablas temporales creadas: TRAIN02 con 120 filas y TEST02 con 30 filas.
Tendré que detenerme aquí, ya que supuestamente este artículo es una nota rápida muy breve.
Simplemente reemplazaremos las secciones 3.3 y 3.4 con PyODBC, PySPark y la API nativa de Python para IRIS, a menos que a alguien no le importe contribuir con una nota rápida - también lo agradeceré.
Buenas tardes,
Puedo conectarme a una base de datos InterSystems Cache DB por medio de PHP o algún otro lenguaje?
Muchas gracias por su ayuda
Saludos
Roman
¡Hola desarrolladores!
Os traemos un nuevo vídeo, grabado por Raj Singh, Product Manager de InterSystems.
⏯ Cómo crear en 10 minutos una app usando Python Flask con InterSystems IRIS
¿Alguien sabe si hay una tabla o consulta para obtener el "Application Error Log (^ERRORS)" por SQL?
¡Hola a tod@s!
El Portal de Administración del Sistema Caché incluye una potente herramienta de consultas en SQL basada en la web, aunque para algunas aplicaciones lo más conveniente es utilizar un cliente dedicado SQL que esté instalado en la PC del usuario.
SQuirreL SQL es un conocido cliente SQL de código abierto construido en Java, que utiliza JDBC para conectarse a un DBMS. Como tal, podemos configurar SQuirreL para que se conecte a Caché usando el controlador JDBC en Caché.
¡Hola Comunidad!
Os traemos un nuevo vídeo, disponible en el Canal de YouTube de la Comunidad de Desarrolladores en inglés: