Cómo agrupar los elementos de una lista por usuario y con el total de veces que el usuario ha hecho un registro?

publicado por: Anonymous

Esta es mi data:

db.define_table('usuarios',
                Field('nombre', 'string'),
                format='%(nombre)s'
                )

db.define_table('registro',
                Field('numero_documento', 'string'),
                Field('usuario', 'reference usuarios'),
                Field('fecha_ingreso', 'date'),
                format='%(numero_documento)s'
                )

estoy tratando de sacar el numero de veces que un usuario ha llenado un registro para ello tomo como base el campo usuario dentro de registro ; estoy pasando los datos a una lista con esta funcion:

def pie_chart():
    query = (db.registro.id > 0)
    data = db(query).select(
        db.usuarios.nombre,
        left=(
            db.usuarios.on(db.usuarios.id==db.registro.usuario),
            )
    )
    new_data=[]
    for row in data:
        row_date = row['usuarios.nombre']
        tmp = [row_date]
        new_data.append(tmp)
    return dict(data=new_data)

con la que me devuelve esta data:

introducir la descripción de la imagen aquí

estaba tratando de sumar y agrupar el numero de registros por usuario asi:

series = []
    cantidad_usuarios = {}
    for line in data:
        usuario = line.usuarios.nombre
        if  usuario not in cantidad_usuarios:
            cantidad_usuarios[usuario] = [0]
        cantidad_usuarios[usuario] += 1
    for nombre, cantidades in cantidad_usuarios.items():
        series.append({
            'name': nombre,
            'data': cantidades
        })

pero no me esta funcionando.

solución

Lo que yo haría es algo similar la respuesta que te di anteriormente, pero orientado al Pie Chart.

La idea acá es más sencilla, es simplemente contar el total de documentos por cada usuario:

import json    

def grafica():
    registros = db(db.registro.id > 0).select(
        db.usuarios.nombre,
        left=(
            db.usuarios.on(db.usuarios.id==db.registro.usuario),
        )
    )
    usuarios = {}
    for registro in registros:
        nombre = registro.nombre
        if nombre not in usuarios:
            usuarios[nombre] = 0
        usuarios[nombre] += 1

    # Pasarlo al formato de Highcharts
    data = []
    for nombre, total in usuarios.items():
        data.append({
            'name': nombre,
            'y': total
        })

    # Los parámetros para el Pie Chart incluyendo la data que calculamos arriba
    parametros = {
        'chart': {
            'plotBackgroundColor': None,
            'plotBorderWidth': None,
            'plotShadow': False,
            'type': 'pie'
        },
        'title': {
            'text': 'Documentos totales por Usuario'
        },
        'tooltip': {
            'pointFormat': '{series.name}: <b>{point.y:.1f}</b>'
        },
        'plotOptions': {
            'pie': {
                'allowPointSelect': True,
                'cursor': 'pointer',
                'dataLabels': {
                    'enabled': True,
                    'format': '<b>{point.name}</b>: {point.percentage:.1f} %',
                }
            }
        },
        'series': [{
            'name': 'Total documentos',
            'colorByPoint': True,
            'data': data
        }]
    }
    parametros = json.dumps(parametros)
    return dict(parametros=parametros)

Finalmente, en tu template:

{{extend 'layout.html'}}
<div id="container" style="min-width: 300px; max-width: 800px; height: 400px; margin: 0 auto"></div>

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        var parametros = JSON.parse('{{=XML(parametros)}}');
        $('#container').highcharts(parametros);
    });
</script>

El resultado sería algo como esto:

introducir la descripción de la imagen aquí

Se muestra el porcentaje general para cada usuario y el detalle del total de documentos por cada usuario.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *