JMP 18 y su funcionalidad Python incorporada brindan acceso a muchas herramientas de código abierto, lo que abre la puerta a la interacción con varias fuentes de datos, ¡incluido SAS! Exploremos cómo se puede aprovechar el paquete Python de código abierto SASPy en el entorno JMP. En este tutorial:
- Instalar SASPy.
- Conectarse a SAS mediante un script de Python.
- Descargue y abra conjuntos de datos de SAS.
- Subir tablas a SAS.
- Ejecutar código SAS.
Si solo le interesa el resumen, consulte los archivos adjuntos para ver ejemplos completos de scripts. Pero si desea repasar el uso de Python con JMP, aquí hay algunas publicaciones de blog que pueden resultarle útiles:
Introducción a la integración de Python en JMP® 18
Creación de funciones JSL implementadas en Python
SASPy: Conexión de JMP con SAS
SASPy , de código abierto y mantenido por SAS, le permite interactuar con SAS mediante Python. SASPy admite conexiones SAS Viya, así como conexiones locales y remotas mediante el Modelo de objetos integrado (IOM). Después de una conexión, se puede utilizar la API robusta para acceder a listas de bibliotecas SAS; obtener información de bibliotecas, listas de tablas e información de tablas; obtener información de columnas individuales; descargar tablas; convertir a y desde Pandas DataFrames; ejecutar código SAS; acceder al registro SAS; utilizar procedimientos de aprendizaje automático y estadístico de SAS; y... tal vez eso sea suficiente por ahora.
Instalación de SASPy con JSL
Comencemos con JSL. Para el tutorial, necesitamos numpy, pandas y SASPy. Ejecute el siguiente script JSL para instalar los paquetes necesarios.
Names Default To Here( 1 );
// install numpy and pandas packages
Python Install Packages( "numpy pandas saspy" );
Verifique que los paquetes se instalen correctamente observando el registro. Solo necesitará instalarlos una vez (suponiendo que se haya realizado correctamente) ya que los paquetes instalados persisten en JMP entre reinicios.
Conectarse a SAS mediante Python
Para conectarse, necesitará conocer cierta información sobre su instancia SAS, es decir, qué tipo de conexión utilizará (Viya o IOM), la ubicación del servidor SAS y las credenciales que necesita para acceder a él.
SASPy es altamente configurable, por lo que debe consultar la documentación de SASPy para conocer su situación de conexión específica. Abordaremos la conexión mediante dos métodos:
- A través de, que se conecta mediante HTTP a una instancia de Viya, no necesita instalar Java. No funcionará con SAS 9.4.
- OIM, que requiere que Java esté instalado en su máquina. Puede acceder a instancias locales en Windows o instancias remotas en cualquier plataforma.
Conectarse usando un diccionario
Comience abriendo una ventana de script de Python de JMP. Abra también el registro integrado haciendo clic derecho y seleccionando "Abrir registro". El script que aparece a continuación utiliza un diccionario de Python que contiene parámetros de conexión. Si reemplaza los parámetros por otros específicos de su instancia de SAS, podrá conectarse. Reemplace la variable en SASSession por el diccionario correspondiente a su tipo de conexión, abra el registro integrado utilizando el menú de clic derecho y ejecútelo.
Nota sobre seguridad: si bien la técnica que se describe a continuación puede ayudar a verificar o depurar su conexión SAS, guardar sus credenciales en un archivo separado donde pueda controlar estrictamente los permisos es probablemente una mejor opción. Hable con el administrador de su sistema para obtener ayuda si no está seguro acerca de las políticas de seguridad de su organización. Si los pasos que se describen a continuación le permiten conectarse, continúe y aplauda, pero luego retire sus credenciales del script siguiendo los pasos de la sección "Conexión mediante un archivo de configuración".
Otra nota: podemos ejecutar Python desde JSL y viceversa, así que al ejecutar el código, asegúrese de verificar la esquina en busca del logotipo azul y amarillo de Python para determinar si está a punto de ejecutar Python o no.
Y una última nota: JMP pasa el control al script Python mientras se ejecuta, por lo que es típico que la GUI no responda mientras se ejecuta el código.
import saspy
viya = {
'url' : 'https://notrealsas.jmp.com:1234', # must contain http or https
'user': 'username',
'pw' : 'password',
'verify' : True, # verify certificates
}
iom = {
# location of java on your machine
'java': r'C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe',
}
iom_remote = {
'java': r'C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe',
'iomhost': 'notrealsas.jmp.com',
'iomport': 1234,
'omruser': 'username',
'omrpw': 'password',
}
# connect to SAS
# replace the second argument with your connection dict, mind the **
sas = saspy.SASsession(prompt=False, **viya)
print(sas)
Una conexión exitosa mostrará algo similar a esto en el registro incorporado:
SAS Connection established. Subprocess id is 10040
Access Method = IOM
SAS Config name = default
SAS Config file = C:\Users\you\AppData\Roaming\JMP\JMP\Python\Python311\site-packages\saspy\sascfg.py
WORK Path = C:\Users\you\AppData\Local\Temp\SAS Temporary Files\_TD16996_SAS-PF4H167P_\Prc2\
SAS Version = 9.04.01M8P01182023
SASPy Version = 5.10.0
Teach me SAS = False
Batch = False
Results = Pandas
SAS Session Encoding = wlatin1
Python Encoding value = cp1252
SAS process Pid value = 16996
Si no puede conectarse, lea atentamente el registro para obtener pistas y verifique también su nombre de usuario y contraseña (si corresponde). Al abrir el registro integrado antes de ejecutar su código, se mostrarán las declaraciones de impresión, así como las excepciones. Otras razones comunes por las que la conexión podría fallar son:
- A través de
- La dirección URL de SAS es inaccesible o está mal escrita.
- No se puede formatear el parámetro 'url' como http(s):// : , por ejemplo, http : //server. jmp . com :5432
- Marcar el campo 'verificar' como "verdadero" cuando la instancia SAS utiliza certificados autofirmados (advertencia: conectarse con verificar=falso es un posible riesgo de seguridad).
- OIM
- No tener Java instalado (es posible que necesite reiniciar JMP o su computadora después de instalar Java).
- Ruta incorrecta al ejecutable de Java. Intente buscar el valor del entorno JAVA_HOME (Mac) o busque la ruta de la carpeta Java (Windows).
Conectarse mediante un archivo de configuración
Ahora, traslademos la información de conexión a otro lugar. Nuevamente, comuníquese con el administrador del sistema para cumplir con las prácticas de seguridad de su organización. Descargue el archivo de configuración de ejemplo (sascfg_personal.py) adjunto a esta publicación y reemplace los valores con sus credenciales. Tome nota de los nombres de configuración SAS_config_names en este archivo para asegurarse de que su opción de conexión esté en esa lista. Luego, conéctese utilizando la ubicación del archivo:
import saspy
# replace with path to your config file
config_file = r'/some/path/to/your/config/sascfg_personal.py'
# replace the cfgname argument with the connection in your config file
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
print(sas)
La salida debería verse igual que cuando se conectó anteriormente.
Abrir un conjunto de datos
Abrir un conjunto de datos descargando un archivo
Una forma de importar conjuntos de datos de SAS es descargar el archivo directamente. JMP puede importar el tipo de archivo de conjunto de datos (sas7bdat), lo que ayuda a preservar los formatos y las etiquetas de los datos. El script de Python que se muestra a continuación descarga un archivo de SAS y utiliza JSL dentro del script de Python para abrir el archivo.
import saspy
import jmp
import tempfile
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
print("Connected to SAS", sas)
table_name = 'cars'
library_name = 'sashelp'
print('Download ' + library_name + '.' + table_name)
data = sas.sasdata(table_name, library_name)
metadata = data.contents()
remote_file = metadata['Enginehost'].query('Label1 == "Filename"')['cValue1'].item()
# save in temp
tmp_dir = tempfile.gettempdir()
print('Copying ' + remote_file + ' to ' + tmp_dir + '...')
sas.download(tmp_dir, remote_file)
print('Opening table...')
jmp.run_jsl('''
dt1 = Open(
"%s/cars.sas7bdat",
Use Labels for Var Names( 1 )
);
''' % (tmp_dir) )
Debería ver una tabla de datos abierta que contiene datos del conjunto de datos Autos.
Abrir un conjunto de datos usando un DataFrame de pandas
SASpy permite convertir conjuntos de datos a/desde un pandas DataFrame, lo que puede resultar útil cuando se utiliza como parte de una canalización de datos que realiza transformaciones, limpieza, creación de datos, etc. JMP también puede importar pandas DataFrames como una tabla JMP, lo que agrega aún más posibilidades.
En el siguiente ejemplo de Python, abrimos el conjunto de datos SASHELP.class como un DataFrame, abrimos una tabla JMP y completamos la tabla JMP con los valores del DataFrame utilizando la función de utilidad definida dataFrameToJmpTable().
import saspy
import jmp
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
def dataFrameToJmpTable(dataFrame, table):
# Populate a jmp data table with a pandas dataframe
# Credit: Paul Nelson
cols = dataFrame.columns
values = dataFrame.values
for (i,k) in enumerate(cols):
print(i, k, dataFrame[k].dtype)
l = values[:,i].tolist() # turn pandas (numpy) column to a list
# create new columns based on the data type of the pandas column
value = values[0,:][i] # get example value from the i'th column
print("Example value: ", value)
if dataFrame[k].dtype == object and isinstance(value, str):
table.new_column(k, jmp.DataType.Character)
table[k] = l
elif dataFrame[k].dtype == 'float64': # numpy.number:
table.new_column(k, jmp.DataType.Numeric)
table[k] = l
elif dataFrame[k].dtype == 'int64': # or 'int32'
table.new_column(k, jmp.DataType.Numeric, dlen=4)
table[k] = l
else:
print('Unhandled column type: {dataFrame[k].dtype} . Defaulting to string.')
table.new_column(k, jmp.DataType.Character)
table[k] = l
sasData = sas.sasdata('Class', 'SASHELP',
results='pandas',
# dsopts={'where':'Age > 12',}
)
dataFrame = sasData.to_df()
values = dataFrame.values
num_rows = len(values)
dt = jmp.DataTable(name='Class', rows=num_rows)
dataFrameToJmpTable(dataFrame, dt)
Si tiene éxito, debería ver la tabla de datos de clase abierta.
Subir archivos a SAS
De manera similar a la descarga de conjuntos de datos, podemos utilizar la interfaz DataFrame proporcionada por SASPy para cargar datos nuevamente en SAS o cargar un archivo JMP. A continuación, se muestra un ejemplo de cómo cargar un archivo de tabla de datos JMP en SAS y luego importarlo mediante el procedimiento PROC IMPORT de SAS:
import saspy
import jmp
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
table_name = 'animals.jmp'
remote_file = sas.workpath + table_name
local_file = jmp.SAMPLE_DATA + table_name
results = sas.upload(local_file, remote_file, overwite=True)
print(results)
# import uploaded file as a data set, replace data set if existing
command = '''
PROC IMPORT OUT= WORK.animals
DATAFILE="{jmp_file}"
DBMS=JMP REPLACE;
RUN;
'''.format(jmp_file=remote_file)
results = sas.submit(command)
print(results)
Verifique el registro incorporado o descargue el archivo para verificar que funcionó.
A continuación se muestra una estrategia de carga mediante DataFrames. Primero convertimos la tabla JMP en un DataFrame y luego la cargamos mediante dataframe2sasdata() :
import saspy
import numpy as np
import pandas as pd
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
def jmpTableToDataFrame(dt) :
# Credit to Paul Nelson again
# Creating a Pandas dataframe from a JMP DataTable
df = pd.DataFrame()
for idx in range( len(dt) ):
if dt[idx].dtype == jmp.DataType.Numeric:
# creates numeric column directly using Python's Buffer Protocol
col = np.array( dt[idx] )
df[ dt[idx].name ] = col.tolist() # make it a list for pandas.
elif dt[idx].dtype == jmp.DataType.Character:
# create a list by iterating through values
col = list()
for i in range ( dt.nrows ):
col.append(dt[idx][i])
# Build character column from list
df[ dt[idx].name ] = col
else:
print("Not adding type:", dt[idx].dtype )
return df
data_table = jmp.open(jmp.SAMPLE_DATA + "Fitness.jmp")
df = jmpTableToDataFrame(data_table)
result = sas.dataframe2sasdata(df, 'Fitness', 'WORK')
print('WORK Tables:', sas.list_tables('WORK'))
Verifique el registro incrustado para ver si la tabla Fitness aparece en la lista de tablas WORK.
En mi experiencia, el uso de archivos completos para la estrategia de carga/descarga tiende a ser la más rápida de las dos estrategias. También limita los problemas de conversión o representación de datos. Por otro lado, los DataFrames son ampliamente aceptados por otros módulos de Python. Recomiendo usar la estrategia de archivos a menos que necesites realizar trabajo adicional de Python en los datos.
Ejecución de código SAS
En la última sección, usamos la función sas.submit() para ejecutar código SAS para importar un archivo, pero podemos hacer esto con cualquier código SAS. Consulta el archivo saspy_cowboy_hat.jsl adjunto para ver un ejemplo que demuestra el uso de SASPy dentro de un script JSL y la ejecución de código SAS para crear y ver un gráfico SAS clásico. Crédito: @bryan_boone y @ChrisHemedinger .
Mirando hacia el JMP 19
Los scripts, complementos y pipelines que utilizan SASpy en JMP 18 seguirán siendo compatibles en JMP 19, lo que significa que puede seguir utilizando y desarrollando cualquier infraestructura creada al trabajar con SAS. Además, JMP 19 ofrecerá una serie de funciones relacionadas con la integración de SAS, lo que aumentará aún más los scripts y las técnicas mencionadas en esta publicación. Volverán algunas funciones conocidas, como el cuadro de diálogo de exportación de SAS y varias funciones de integración de SAS de JSL. Todas están basadas en la infraestructura del conector de datos para permitir configurar, compartir y utilizar fácilmente las conexiones SAS en toda su organización.
¿Tiene JMP 18 actualmente y desea probar las futuras funciones de integración de SAS antes de que JMP 19 entre en producción? Una excelente manera de proporcionar comentarios y orientación específicos es postularse al programa Early Adopter (EA) de JMP 19. Visite jmp.com/earlyadopter para obtener más información.
Al incorporar las robustas herramientas de código abierto que Python proporciona a JMP, se abren muchas oportunidades para acceder a los datos e interactuar con ellos. El script de demostración completo de SASPy se puede encontrar adjunto a esta publicación.
Además, un gran agradecimiento a Tom Weber por apoyar a SASPy. Como paquete de código abierto, considere contribuir con mejoras o sugerencias a SASPy en github .
¡Feliz scripting a todos!
Recursos
Configuración de SASPy
API de Python de SASPy
Ejemplo de cuadernos de Júpiter de SASPy
Documentación de pandas