Haciendo cálculos




Envision le ofrece la posibilidad de llevar a cabo casi cualquier cálculo que podría realizarse con Excel. En este sentido, la sintaxis para realizar esos cálculos es similar a la sintaxis utilizada por las fórmulas de Excel. Envision pone el énfasis en los cálculos vectoriales. Las operaciones basadas en vectores se utilizan para procesar muchos valores al mismo tiempo, en lugar de trabajar con cada valor individual por vez. En esta sección, hablaremos más en detalle sobre las tablas y los vectores, lo cual debería resultarle de ayudar para comenzar a realizar sus propios cálculos con Envision.

Para seguir mejor el contenido de esta página, le sugerimos que configure el conjunto de datos de ejemplo. Aún no hemos detallado las capacidades de Envision relativas a la carga de datos de entrada, pero nuestros ejemplos le mostrarán las líneas que tiene que poner al principio de su script.

Tablas y vectores

El modelo de datos de Envision gira en torno a tablas y vectores. Una tabla de Envision es similar a las tablas que existen en las bases de datos relacionales. Desde una perspectiva de Excel, una tabla es una planilla de cálculo bien formada en la cual la primera línea contiene los encabezados de la columna y en la que las (varias) líneas debajo contienen datos que se alinean correctamente con estos encabezados. En un script de Envision, las tablas también tienen nombres, que generalmente derivan de los nombres de los archivos tabulados subyacentes. Los vectores se asocian a las columnas en una tabla y, de modo similar, también llevan nombres. Envision utiliza el término "vector" en lugar de "columna" para enfatizar que las operaciones pueden realizarse en todos los valores vectoriales a la vez, es decir, en todas las líneas de la tabla original.

Ilustremos esta idea con unas pocas líneas de script que pueden aplicarse al conjunto de datos de ejemplo. A continuación, para cada línea de orden, calculamos la tasa impositiva, es decir, la proporción entre el monto de impuestos y el monto al neto de impuestos que se le cobra al cliente.
read "/sample/Lokad_Items.tsv"
read "/sample/Lokad_Orders.tsv" as O
read "/sample/Lokad_PurchaseOrders.tsv" as PO

O.TaxRate = Or.TaxAmount / O.NetAmount
Aquí, Or se refiere a la tabla de pedidos, es decir, la que contiene todo el historial de ventas, con cada transacción representada con tantas líneas como artículos haya dentro de la transacción dada. La variable O.TaxAmount se refiere al vector asociado con la columna llamada TaxAmount en la tabla O. Será útil que recuerde la sintaxis, que consiste en utilizar un punto (.) entre el nombre de la tabla y el nombre del vector, ya que este patrón se utiliza con frecuencia en Envision.

La operación que incluye el signo igual = se denomina asignación: el cálculo tiene lugar a la derecha del signo =, y el resultado se asigna a la izquierda de la instrucción. En el ejemplo anterior, tenemos una operación de división que tiene lugar del lado derecho. Debido a que ni O.TaxAmount ni O.NetAmount están realmente definidos en ningún lado en el script, Envision intenta cargar estos datos directamente desde el conjunto de datos de entrada. Debido a que la tabla O del conjunto de datos de la tabla contiene las dos columnas NetAmount y TaxAmount, el script se ejecuta correctamente. Luego, a la izquierda, tenemos O.TaxRate, que se asigna a la tasa impositiva que se acaba de calcular. Una asignación es el equivalente lógico de crear una nueva columna en Excel a la que se le pone el nombre de acuerdo con la variable de la asignación, es decir, en este caso, TaxRate.

En los siguientes fragmentos de código, para ser concisos, omitimos las líneas read “/sample/Lokad_XYZ.tsv” en todos los ejemplos, ya que se espera que siempre estén incluidas al principio de cada script.

La sintaxis para los cálculos en Envision es similar a la utilizada para las fórmulas de Excel. En el script a continuación, realizamos una serie de cálculos (bastante arbitrarios) para ilustrar esta sintaxis.
O.A = 42
O.B = 5 * (1+ O.A)
O.C = (O.A + O.B) * (1 + O.A)
Aquí, el script define tres vectores llamados respectivamente A, B y C; y los tres vectores se adjuntan a la tabla O. La primera línea es una simple asignación en la que se asigna el valor 42 a O.A. Sin embargo, debido a que O.A es un vector, no es solo un valor de 42, sino un valor para cada línea de la tabla original. Envision pone el énfasis en los vectores, y la mayoría de las operaciones en vectores tiene lugar en todos sus valores a la vez.

Luego, O no es la única tabla disponible en el conjunto de datos de ejemplo. Por ejemplo, el conjunto de datos de ejemplo contiene una tabla PO, y se pueden realizar operaciones muy similares también en esta tabla.
PO.A = 42
PO.B = 5 * (1+ PO.A)
PO.C = PO.A + PO.B
Debido a que acabamos de introducir una segunda tabla, se presenta la pregunta: ¿puede Envision llevar a cabo operaciones entre tablas? La respuesta es que sí, pero requiere un poco más de esfuerzo. Consideremos el siguiente script:
O.A = 1
PO.A = O.A + 1 // ERRÓNEO
Debido a que las dos tablas O y PO no tienen motivo para estar alineadas en modo alguno —las tablas ni siquiera contienen la misma cantidad de líneas—, la semántica asociada a tal operación sería muy confusa. Por lo tanto, una operación de este tipo no es válida en Envision, y si se intenta ejecutar un script como ese, la ejecución fallará y se mostrará un mensaje de error.

No obstante, Envision proporciona varios modos para combinar datos de tablas distintas, y este aspecto se cubre en la sección siguiente.

Tabla especial de “artículos”

Las tablas utilizadas por Envision llevan nombres; sin embargo, existe una excepción importante a esta convención: la tabla artículos. De hecho, en el comercio, observamos que para la gran mayoría de los cálculos, existe una tabla que domina sobre todas las demás: la lista de productos / variantes / SKU / etc., dependiendo del contexto de negocio real que se considera. A diferencia de, por ejemplo, las bases de datos relacionales, en las que todas las tablas se tratan como si fueran iguales, Envision le da un tratamiento especial a la tabla artículos, lo que simplifica la gestión de la mayoría de los escenarios encontrados en el comercio.

En algún punto de su existencia, todo comerciante, pequeño o grande, logra generar una planilla de cálculo en la figura la lista de todos los productos, un producto por línea, y que incluye varias columnas adicionales que proporcionan información extra, ya sea estática, como categorías de producto, o dinámica, como el total de ventas en las últimas 5 semanas. Dependiendo de la situación, las líneas se asociarán a productos o SKU, o a cualquier representación detallada similar de los artículos que se están vendiendo. La elaboración de una tabla consolidada de este tipo es práctica en muchas situaciones: al identificar inventario muerto, al actualizar precios, al identificar principales artículos más vendidos, etc. Como profesional minorista, probablemente haya trabajado con este tipo de planillas de cálculo en varias ocasiones.

En Lokad, nos hemos dado cuenta de que esas planillas de cálculo son omnipresentes en el comercio minorista, y decidimos reflejar esto en nuestra tecnología. Hemos diseñado Envision para que capture este patrón en detalle, de modo que nos permita mantenernos lo más alineados posible con esta práctica tan predominante en el comercio.

Regresemos al conjunto de datos de ejemplo. Este conjunto de datos contiene un lista de artículos. Supongamos que quisiéramos calcular el valor del inventario de cada artículo. Si la tabla "artículos" se llamara Items, esto se podría hacer con:
Items.Stock = Items.StockOnHand + Items.StockOnOrder 
Items.StockValue = Items.TotalStock * BuyPrice
Sin embargo, para la tabla “artículos”, y solo para esa tabla, el nombre de la tabla puede omitirse. Por lo tanto, el script debería escribirse de este modo:
Stock = StockOnHand + StockOnOrder 
StockValue = Stock * BuyPrice
El prefijo Items. ha sido eliminado y, por convención, cualquier variable cuyo nombre no incluye un punto (.) refiere implícitamente a un vector asociado con la tabla “artículos”. Debido a que los cálculos que incluyen "artículos" son muy frecuentes en el comercio, esta convención hace que Envision sea mucho más legible en la práctica.

Una de las razones clave por las que las planillas de cálculo "artículos" se utilizan tanto es que la mayoría de los datos históricos encontrados en el comercio pueden representarse convenientemente como una lista de eventos en los que cada evento está unido a un artículo. Por ejemplo, el historial de ventas es —como mínimo— una tabla con tres columnas: el identificador de artículo, la fecha y la cantidad comprada. De modo similar, el historial de ventas puede representarse con las mismas tres columnas, más, en un escenario ideal, una fecha de llegada para dar cuenta del tiempo de entrega entre el pedido y la entrega. Las devoluciones de clientes también pueden representarse como un tabla que contiene las columnas que incluyen el identificador de artículo, la fecha, la cantidad e idealmente el identificador de cliente, si uno está interesado en analizar el comportamiento de clientes recurrentes.

Y la lista continúa. En el comercio, se trata de los flujos: flujos de bienes, de proveedores a clientes; y flujos de dinero, de clientes a proveedores. Tales flujos pueden descomponerse en líneas elementales en las que cada línea está unida a un artículo en particular. Por lo tanto, en el comercio, no estamos buscando cualquier tipo de tabla, sino que estamos buscando las tablas que en general giran en torno a los artículos, y este es exactamente el patrón que pretende capturar Envision.

La tabla "artículos" tiene solo una columna que es obligatoria: la columna del identificador de artículo, que debería llevar el nombre "Id" siguiendo las convenciones de Envision. Se espera que casi todas las demás tablas cargadas en Envision tengan una columna "Id" propia. Hemos visto antes que no era posible combinar la tabla O con la tabla PO, porque no estaban alineadas. Pues bien, la columna Id que se encuentra en ambas es precisamente el "puente" que se necesita para permitir que esta combinación tenga lugar.

Ilustremos esto con un cálculo de efectivo. Supongamos que para cada artículo, uno quisiera calcular la entrada de efectivo asociada con el historial de ventas completo, y la salida de efectivo, también asociada con el historial de compras completo. Esto puede realizarse con el script a continuación.
CashIn = sum(O.NetAmount)
CashOut = sum(PO.NetAmount) 
CashFlow = CashIn - CashOut
Aquí, vemos que tenemos los "artículos" en el lado izquierdo de las asignaciones, y las demás tablas en el lado derecho, al menos para las líneas 1 y 2. El uso de diferentes tablas simultáneamente es legítimo en este caso por el uso del agregador sum(). No revisaremos el agregador en detalle en este documento, pero basta decir que, como el nombre lo sugiere, el agregador sum() calcula la suma de cada NetAmount para cada artículo. La correspondencia entre los artículos y las órdenes se realiza de modo transparente, porque la tabla O también viene con una columna Id.

Hemos descompuesto el cálculo en tres líneas para que se vea claramente. Sin embargo, el script puede escribirse de un modo más compacto, sin nombrar las variables intermedias, del modo siguiente:
CashFlow = sum(O.NetAmount) - sum(PO.NetAmount)
Además de la suma, Envision es compatible con los agregadores clásicos: promedio, mín, máx, mediana, etc., y estos agregadores ofrecen muchas posibilidades para complementar la tabla artículos con atributos descriptivos que pueden ser muy útiles cuando se trata de abordar muchos de los desafíos que se presentan en el comercio. Sin embargo, si bien es posible crear un nuevo vector dentro de los "artículos", aprovechando otra tabla y un agregador, también es posible hacer lo contrario y utilizar un vector de la tabla "artículos" cuando se realiza un cálculo asociado con otra tabla.

Consideremos una situación en la que uno quisiera recalcular el IVA (impuesto al valor agregado) asociado con cada línea de orden de ventas. Para simplificar, supongamos que el IVA se calcula a una tasa plana de 20 % en todos los artículos y para todo el historial. Esto podría escribirse del siguiente modo:
VatRate = 0.2 // hipótesis
F = VatRate / (1 - VatRate)
O.Vat = O.NetAmount * F
El vector VatRate se expande naturalmente hacia un vector alineado con la tabla O, porque cada línea de orden está vinculada a un solo artículo original. Esta expansión se puede hacer más explícita escribiendo el código real:
VatRate = 0.2 // hypothesis
O.VatRate = VatRate
O.F = O.VatRate / (1 - O.VatRate)
O.Vat = O.NetAmount * O.F
En los ejemplos anteriores, los vectores F se introducen simplemente para ilustrar la descomposición del cálculo.

Como información adicional, tenga en cuenta que es de hecho posible cargar tablas arbitrarias en Envision, incluso cuando tales tablas no incluyan una columna Id. Sin embargo, tales escenarios avanzados exceden el alcance de la presente discusión.

Estado especial de fechas

La tabla artículos es un caso especial en Envision, porque, como hemos visto, muchas operaciones fundamentales del comercio giran en torno a la noción de "artículos": Sin embargo, tales operaciones también están generalmente vinculadas a una fecha específica. Cada línea del historial de ventas viene con una fecha aplicable; lo mismo sucede con el historial de órdenes de compra, y esto se verifica también en casi todos los datos que calificarían como datos históricos. Debido a la importancia de los datos históricos en el comercio, donde prácticamente todas las operaciones de negocios pueden describirse como una lista de entradas fechadas que dan cuenta de los movimientos de existencias o de los pagos, Envision le presta especial atención a las fechas en un modo orientado al comercio.

Cualquier tabla puede tener una columna Date además de su columna canónica Id. Cuando está presenta una columna Date, la tabla no solo está indexada por identificadores de artículo, sino también por fechas. La indexación por fechas es práctica, porque, a menudo, cuando uno busca aplicar una ventana de tiempo de alguna clase a un cálculo, se espera que el historial completo, sin importar el tipo de entradas implicadas, se filtre de modo similar.

Para ilustrar esto, regresemos a nuestro cálculo de flujo de efectivo. Supongamos que, en lugar de calcular valores para todo el historial, decidimos calcular el flujo de efectivo por artículo, tomando solo el último año del historial de datos. Esto puede realizarse con:
end := max(date)
when date > end - 365
  CashFlow = sum(O.NetAmount) - sum(PO.NetAmount)
La variable end se define como los datos más recientes observados en todo el conjunto de datos de entrada. Debido a que end es una fecha, esto demuestra que Envision ofrece la posibilidad de llevar a cabo aritmética de fechas, como se muestra en el script anterior. La adición de la convención +1 a cualquier fecha en Envision tiene como resultado la adición de un día a esa fecha específica. Por lo tanto, al restar 365 días, retrocedemos aproximadamente un año.

El script comienza con un filtro when que representa una condición que se impone como verdadera para todas las líneas procesadas dentro de un determinado bloque de script. En cuanto a los artículos, no están indexados por fecha, por lo que el filtro de fecha no tiene efecto sobre ellos, y todos los artículos siguen estando presentes dentro del bloque when. Sin embargo, tanto las órdenes de compra como las de venta tienen una columna Date propia y, como resultado, todas las líneas que no satisfacen la condición del filtro when se filtran del bloque de script.

Como consecuencia, la agregación sum() dentro del bloque when procesa las líneas no filtradas, es decir, las líneas que tienen menos de un año de antigüedad. El mismo cálculo podría haberse realizado con variables intermedias, del mismo modo que se hizo inicialmente con el ejemplo del historial completo.
end := max(date)
when date > end - 365
  CashIn = sum(O.NetAmount)
  CashOut = sum(PO.NetAmount)
  CashFlow = CashIn - CashOut
Con el ejemplo anterior, probablemente resulte más claro por qué nos utilizamos la instrucción when al comienzo del bloque de filtrado: todas las líneas dentro del bloque, destacadas por los dos espacios adicionales al inicio de las líneas 2, 3 y 4, pasan por el mismo filtro ambiental para las fechas.

El script también ilustra la capacidad de Envision para realinear datos complejos que provienen de otras tablas con la tabla "artículos". Desde una perspectiva de Excel, es como si uno pudiera transformar las demás planillas (por ejemplo, el historial de órdenes) en columnas utilizando la planilla maestra que contiene la lista de productos. Envision hace que este proceso sea mucho menos tedioso.