Redondear decimales en Pandas con round y decimal

logo pandas

En esta ocasión hablaré de como redondear decimales en Pandas con round() y decimal().

Ya en antes, he hablado, de lo que significa, y cómo aplicar el redondeo de la mejor forma posible en Python.

Sabemos, que existen múltiples ocasiones, en las que podemos necesitar sustituir un valor de tipo entero, por otro con una cantidad de decimales dada;  o directamente asignar solo una cantidad de decimales a todos los valores dentro de una dataframe.

Veamos un ejemplo para mostrar las diferentes opciones.

Primero importamos las librerías.

Importamos el dataframe

Redondear decimales usando round() en Pandas

Es una función que  redondea un número de coma flotante, al número de lugares decimales proporcionados como segundo argumento de la función.

Su sintaxis es round(value, numero de decimales)

En este ejemplo redondeamos la columna 2 de un dataframe

Primero aplicamos la función series() de Pandas, definimos la función round() con los espacios que deseamo, para luego aplicar un bucle for, para recorrer la columna.  

En este caso la labor de round(), es colocar una coma flotante, y dejar la cantidad de decimales que le indicamos al redondear, como segundo parámetro.

Format() como apoyo

Otra forma, es utilizar format(), pero como su nombre indica, por si sola, no redondea, sino que formatea la salida de la cadena, dandole la estructura que deseamos.

format() es una propiedad de string, o sea trabaja con una cadenas, y por lo tanto no debe confundirse con valores numéricos

La sintaxis es algo como lo que sigue, cuando la usamos en solitario, aunque existen multiples combinaciones para aplicar formato.

En este caso estamos formateando la salida de un valor a porcentaje con solo dos decimales.

df['columna3'] = pd.str(["{0:.2f}%".format(val * 100) for val in df[' columna3']])

El formato de cadena le permite representar los números como desee. Puede cambiar el número de lugares decimales que se muestran cambiando el número antes de la f.  

Redondear decimales usando Decimal

Cuando necesitamos una adecuada precisión es recomendable usar decimal, ya que es mucho mas adecuado que round(), si buscamos exactitud.

Puedes ver este articulo sobre la diferencia entre round() y decimal()

La construcción de la sintaxis es como se ve en el ejemplo:

En el primer caso, solo ejecutamos una división, donde obtenemos un número de coma flotante.

En los ejemplos siguientes, lo que hacemos en indicarle a Python que estamos esperando un resultado en formato decimal.

En el segundo tomamos algunas de las propiedades del contexto y le decimos a Decimal que tipo de redondeo queremos.

En el tercer y ultimo calculo, solo tomamos el contexto predeterminado e indicamos el nivel de precision que deseamos.

En todos los casos hemos redondeado a dos espacios pero podríamos haber fijado cualquier cantidad de dígitos, que necesitáramos.

..se me ha olvidado ya el lugar de donde vengo, y puede que no exista el sitio adonde voy…

J.Sabina

Relaciones en Laravel

laravel

Establecer y definir correctamente las relaciones en Laravel cuando construimos una APP, es uno de los pasos más importantes para lograr una solución solida y escalable.

Las relaciones que se dan entre los modelos son la base de todo lo que haremos después.

Laravel aporta una estructura sencilla para construir sus modelos y relaciones, dentro del mundo de Eloquent, el cual aporta un conjunto de convenciones, que en esencia son estas

Convenciones de Eloquent Model

Los nombres de la tablas se escriben en minúsculas, corresponderán con el nombre del modelo y se le agrega una  s, y   si el modelo   tiene un nombre compuesto por dos palabras, la s se añade al final de todo, separando las palabras con una guion bajo.

De este modo , la tabla del modelo Cliente sería clientes y la de ClienteLike sería cliente_likes.
El campo primary key de una tabla debe tener el nombre de id, con el atributo AUTO_INCREMENT, en laravel 5 o bigIncrements en Laravel 6.

Los modelos son clases extienden de la clase Model, un modelo al ser creado tiene esta estructura

 <?php namespace App; use Illuminate\Database\Eloquent\Model; class NombreModelo extends Model {     // } 

Es aquí donde definiremos las relaciones y estructura del modelo, esto incluye la tabla a que se refiere, los campos que deberán ser llenados dentro de su tabla, y los cambios que queramos hacer en la estructura de la tabla que corresponde al modelo.

Otros Posts sobre Laravel

Las convenciones no son inviolables, sino una guía de organizar el código y su legibilidad pero pueden cambiarse todo lo que se desee dentro del modelo.  Por ejemplo un modelo Productos variado puede quedar así

class Producto extends Model
 {
     // cambiamos el nombre de la tabla que controla el modelo en vez de productos, trabajara con mercancia
     protected $table = 'mercancia';
 // cambiamos la clave primaria, que por defecto es id pero usaremos el código ean definiendo ese campo en la propiedad  primaryKey protected $primaryKey = 'ean_code'; // Anulamos los valores por defecto de los campos  timestamp que Laravel crea automáticamente en cada tabla, cambiando su valor a false public $timestamps = false; // asignamos  un nombre de conexión diferente protected $connection = 'connection-name'; // Establecemos aquellos atributos  a los que se les pueden asignar valores protected $fillable = ['name',’fabricante’]; // Definimos en la variable guarded, los atributos que no pueden se asignados protected $guarded = ['price',’expire_date’];
 }
 <?php namespace App; use Illuminate\Database\Eloquent\Model; class Producto extends Model {     // cambiamos el nombre de la tabla que controla el modelo en vez de  productos, trabajara con mercancia     protected $table = 'mercancia';       // cambiamos la clave primaria, que por defecto es id pero usaremos  el código ean definiendo ese campo en la propiedad  primaryKey     protected $primaryKey = 'ean_code';       // Anulamos los valores por defecto de los campos  timestamp que  Laravel crea automáticamente en cada tabla, cambiando su valor a false     public $timestamps = false;       // asignamos  un nombre de conexión diferente     protected $connection = 'connection-name';       // Establecemos aquellos atributos  a los que se les pueden asignar  valores     protected $fillable = ['name',’fabricante’];       // Definimos en la variable guarded, los atributos que no pueden se  asignados     protected $guarded = ['price',’expire_date’]; } 

Las relaciones pueden ser de uno a uno, de uno  a muchos o de muchos a muchos, hay suficiente información sobre esto en la red, muy bien explicado, pero en esencia en una aplicación donde un cliente, con un buzón de correos individual,  tendrá más de un rol, y habrá varios usuarios de la misma empresa, los modelos quedarían relacionados así.

Un cliente  con un buzón de correo (de uno a uno), pertenece solo a una empresa (de uno a uno) y un cliente tiene varios roles(relación de uno a muchos)

Como puede verse las relaciones son bilaterales, por tanto la inversa es que entre buzon y cliente también es de uno a uno, entre empresa    y clientes hay una relación de muchos a  uno  y entre roles y cliente también de uno a varios.

Cuando en ambos lados la relación es de uno a muchos,  se considera una relación de muchos a muchos y debe crearse una tabla pivote que acoja solo aquellos valores de ambos modelos que no son coincidentes y que será la tabla objeto de las consultas.

Si a las relaciones son de uno a muchos de  un lado y de uno a uno en el otro, es una relación de general de uno a muchos y si ambos lados son de uno a uno, pues asi queda de uno a uno.

Uno a Uno

Ejemplo Cliente y Buzón están relacionados uno a uno

namespace App;
use Illuminate\Database\Eloquent\Model;
class Cliente extends Model
{
public function buzon()
{
return $this->hasOne('App\Buzon');
// Si el id tiene un nombre diferente al que corresponde por convención buzons_id lo especificamos
return $this->hasOne('App\Buzon', 'code_id', 'local_key');
}
}

Definimos la otra clase

namespace App;
use Illuminate\Database\Eloquent\Model;
class Dni extends Model
{
public function cliente()
{
return $this->belongsTo('App\Cliente');
// Si el id tiene un nombre diferente al que corresponde por convención clientes_id lo especificamos
return $this->belongsTo('App\Cliente', 'nombre_id', 'local_key');
}
}

Uno a Muchos

En esta caso la definición es prácticamente igual

Una Empresa tiene muchos Clientes

namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function clientes()
{
return $this->hasMany('App\Cliente');
// Si el id tiene un nombre diferente al que corresponde por convención clientes_id lo especificamos
return $this->hasMany('App\Cliente', 'name_id', 'local_key'); }
}

Un Cliente pertenece a una Empresa

namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function empresa() { return $this->belongsTo('App\Empresa'); }
}

Muchos a Muchos

Un Cliente tiene varios Roles

namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function roles() { return $this->belongsToMany('App\Role');
// Si el nombre de la tabla es diferente a lo predeterminado o el ID de la tabla tiene otro nombre.
return $this->belongsToMany('App\Role', 'cliente_roles', 'name_id', 'defin_id');
}
}

Un Rol tiene varios Clientes

namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function clientes() { return $this->belongsToMany('App\Cliente');
// Si el nombre de la tabla es diferente a lo predeterminado o el ID de la tabla tiene otro nombre.
return $this->belongsToMany('App\User', 'cliente_roles', 'defin_id', 'name_id');
}
}

Aquí debemos crear una tabla intermedia, con el nombre cliente_roles, de las cual será donde obtengamos los datos. La idea básica es que esta tabla tendrá los id de las tablas que la conforman y otros campos que sean interesantes tener para nuestra aplicación

Definimos en la función withPivot los campos de la tabla intermedia, y el acceso a ellos.

namespace App;
use Illuminate\Database\Eloquent\Model;
class Cliente extends Model
{
public function roles()
{
return $this->belongsToMany('App\Role', 'cliente_roles')
->withPivot('create', 'read','update', 'delete');
}
}

Y para acceder  a los datos intermediamos la palabra pivot en la solicitud/orden  que hacemos. 

$user = App\Cliente::find(1);
foreach ($cliente->roles as $role) {
    echo $role->pivot->create;
}

Ademas podemos acceder directamente a las tablas para obtener diferentes resultados

// retorna App\Buzon
App\Cliente::first()->buzon;

Nos devolverá valores del modelo Buzon

// retorna Illuminate\Database\Eloquent\Relations\BelongsToMany
App\Cliente::first()->roles();

Nos devolverá valores del modelo Role, de acuerdo a su relación con el modelo cliente

// retorna Illuminate\Database\Eloquent\Collection
App\Cliente::first()->roles;
Nos devolverá una colección 

Y listo, esto es todo.

Espero modestamente que este artículo, sirva de ayuda a alguien.

Gracias.

…., si avanzo sígueme, si me detengo empújame, si retrocedo mátame…….

Error IsADirectoryError

python error

IsADirectoryError  es un  tipo de error que puede aparecer en Python, cuando intentamos acceder a un archivo de forma errónea.

El error suele tener esta forma:

Traceback (most recent call last):
  File "miprograma.py", line 38, in <module>
    archivo()
  File "miprograma.py", line 28, in archivo
    descarga = open('/Volumes/MasterData/tiendas/informatica/tienda01/descargas', 'wb').write(miarchivo.content)
IsADirectoryError: [Errno 21] Is a directory: '/Volumes/MasterData/tiendas/informatica/tienda01/descargas'

Como puede verse, lo que sucede es que hemos escrito mal la ruta y en vez de dirigirla la petición hacia un archivo, la estamos dirigiendo a una carpeta.

Esto puede suceder cuando copiamos y pegamos, generalmente porque no hemos escrito el nombre del archivo.

Otros post sobre errores en Python

Espero modestamente, que este post haya ayudado a alguien.

Tres cosas necesitan las ovejas para andar en manadas, el miedo al perro, la voz de amo y que la de atrás temiendo quedarse sola empuje.

Y.
Translate »