Alla ricerca

(di superficie)

del valore dei dati

Analisi automatica della qualità dei dati

Andrea Borruso @aborruso

Comodo partire da un catalogo (dati)

  • è un indice strutturato e descritto
  • è predisposto per un'analisi massiva
  • esistono standard per descriverli

Il catalogo italiano dei dati aperti

Il catalogo dei dati aperti del Comune di Palermo

Il catalogo dei dati aperti del Comune di Palermo

  • Un'analisi delle risorse
    • misurarle
    • descriverle
    • valutarne la qualità
- name: openDataComunePalermo
  description: Catalogo Open Data Comune Palermo
  URL: https://opendata.comune.palermo.it/dcat/dcat.php
  type:
   name: DCAT-AP_IT
   version: "1.0"
<https://opendata.comune.palermo.it/js/server/uploads/dataset/csv/_21022013104349.csv>
  a dcatapit:Distribution, dcat:Distribution ;
  dcat:downloadURL <https://opendata.comune.palermo.it/js/server/uploads/dataset/csv/_21022013104349.csv> ;
  dcat:accessURL <https://opendata.comune.palermo.it/opendata-dataset.php?dataset=78> ;
  dc:format <http://publications.europa.eu/resource/authority/file-type/CSV> ;
  dc:license <https://creativecommons.org/licenses/by/4.0/> ;
  dc:title "Distribuzione CSV del dataset ISTITUTI PREVENZIONE E PENA ANNO  MOVIMENTO DETENUTI ANNO 2010-2011" ;
  dc:description "Distribuzione CSV del dataset ISTITUTI PREVENZIONE E PENA ANNO  MOVIMENTO DETENUTI ANNO 2010-2011" .

Sono "pronti"?

curl -I https://opendata.comune.palermo.it/js/server/uploads/dataset/csv/_08072016115204.csv

HTTP/1.1 404 Not Found
Date: Fri, 16 Apr 2021 20:00:01 GMT
Server: Microsoft-IIS/6.0 mod_fcgid/2.3.9
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer-when-downgrade
Connection: close
Content-Type: text/html; charset=iso-8859-1

Quali formati?

+-----------+-------+
| format    | count |
+-----------+-------+
| XML       | 685   |
| CSV       | 418   |
| ZIP       | 87    |
| OP_DATPRO | 22    |
| KML       | 24    |
| SHP       | 1     |
+-----------+-------+

Il valore di un report (automatico)

  • monitoraggio
  • risparmio risorse
  • prendersi cura
  • condividere

Errori

Righe vuote

162.csv

Errore di "tipo"

121.csv

"Etichetta" mancante

384.csv

"Etichetta" duplicata

179.csv

"Etichetta" scorretta

357.csv

Frictionless
framework

Per dati senza attrito

Frictionless

Generare informazioni e conclusioni dai dati spesso non è un processo semplice.

I dati possono essere strutturati male, difficili da trovare, archiviati in formati difficili da usare o incompleti.

Frictionless

  • Descrivere
  • Estrarre
  • Validare
  • Trasformare

hands on ...

Validate

{
  "version": "4.7.1",
  "time": 0.084,
  "errors": [],
  "tasks": [
    {
      "resource": {
        "path": "../output/openDataComunePalermo/rawdata/download/418.csv",
        "name": "418",
        "profile": "tabular-data-resource",
        "scheme": "file",
        "format": "csv",
        "hashing": "md5",
        "encoding": "iso8859-1",
        "dialect": {
          "delimiter": ";"
        },
        "schema": {
          "fields": [
            {
              "name": "Scuole Elementari Pubbliche",
              "type": "string"
            },
            {
              "name": "Anno 2010 2011",
              "type": "string"
            },
            {
              "name": "Anno 2009 2010",
              "type": "string"
            }
          ]
        },
        "stats": {
          "hash": "ea4c391cff38a0729b077aa52186a562",
          "bytes": 424,
          "fields": 3,
          "rows": 12
        }
      },
      "time": 0.084,
      "scope": [
        "hash-count-error",
        "byte-count-error",
        "field-count-error",
        "row-count-error",
        "blank-header",
        "extra-label",
        "missing-label",
        "blank-label",
        "duplicate-label",
        "incorrect-label",
        "blank-row",
        "primary-key-error",
        "foreign-key-error",
        "extra-cell",
        "missing-cell",
        "type-error",
        "constraint-error",
        "unique-error"
      ],
      "partial": false,
      "errors": [],
      "stats": {
        "errors": 0
      },
      "valid": true
    }
  ],
  "stats": {
    "errors": 0,
    "tasks": 1
  },
  "valid": true
}
frictionless validate input.csv

Frictionless validate

$ frictionless validate 147.csv                                                                                                                                                                                                  1 ↵
# -------
# invalid: ../output/openDataComunePalermo/rawdata/download/147.csv
# -------

====  =====  ==========  ======================================================================================================================================
row   field  code        message
====  =====  ==========  ======================================================================================================================================
2077      1  type-error  Type error in the cell "senza fissa dimora" in row "2077" and field "Sezione di censimento" at position "1": type is "integer/default"
====  =====  ==========  ======================================================================================================================================

Frictionless validate

{
  "version": "4.7.1",
  "time": 1.187,
  "errors": [],
  "tasks": [
    {
      "resource": {
        "path": "../output/openDataComunePalermo/rawdata/download/147.csv",
        "name": "147",
        "profile": "tabular-data-resource",
        "scheme": "file",
        "format": "csv",
        "hashing": "md5",
        "encoding": "utf-8",
        "dialect": {
          "delimiter": ";"
        },
        "schema": {
          "fields": [
            {
              "name": "Sezione di censimento",
              "type": "integer"
            },
            {
              "name": "Unione europea",
              "type": "integer"
            },
            {
              "name": "Europa centro orientale",
              "type": "any"
            },
            {
              "name": "Altri paesi europei",
              "type": "any"
            },
            {
              "name": "Africa settentrionale",
              "type": "integer"
            },
            {
              "name": "Africa occidentale",
              "type": "integer"
            },
            {
              "name": "Africa orientale",
              "type": "integer"
            },
            {
              "name": "Africa centro meridionale",
              "type": "any"
            },
            {
              "name": "Asia occidentale",
              "type": "any"
            },
            {
              "name": "Asia centro meridionale",
              "type": "integer"
            },
            {
              "name": "Asia orientale",
              "type": "integer"
            },
            {
              "name": "America settentrionale",
              "type": "any"
            },
            {
              "name": "America centro meridionale",
              "type": "any"
            },
            {
              "name": "Oceania",
              "type": "any"
            }
          ]
        },
        "stats": {
          "hash": "d01805b66dd530dca16d68d0c32a79c1",
          "bytes": 43063,
          "fields": 14,
          "rows": 2076
        }
      },
      "time": 1.187,
      "scope": [
        "hash-count-error",
        "byte-count-error",
        "field-count-error",
        "row-count-error",
        "blank-header",
        "extra-label",
        "missing-label",
        "blank-label",
        "duplicate-label",
        "incorrect-label",
        "blank-row",
        "primary-key-error",
        "foreign-key-error",
        "extra-cell",
        "missing-cell",
        "type-error",
        "constraint-error",
        "unique-error"
      ],
      "partial": false,
      "errors": [
        {
          "cell": "senza fissa dimora",
          "fieldName": "Sezione di censimento",
          "fieldNumber": 1,
          "fieldPosition": 1,
          "cells": [
            "senza fissa dimora",
            "1",
            "",
            "",
            "8",
            "4",
            "1",
            "",
            "4",
            "",
            "",
            "",
            "",
            ""
          ],
          "rowNumber": 2076,
          "rowPosition": 2077,
          "code": "type-error",
          "name": "Type Error",
          "tags": [
            "#table",
            "#row",
            "#cell"
          ],
          "note": "type is \"integer/default\"",
          "message": "Type error in the cell \"senza fissa dimora\" in row \"2077\" and field \"Sezione di censimento\" at position \"1\": type is \"integer/default\"",
          "description": "The value does not match the schema type and format for this field."
        }
      ],
      "stats": {
        "errors": 1
      },
      "valid": false
    }
  ],
  "stats": {
    "errors": 1,
    "tasks": 1
  },
  "valid": false
}

Posso fare molto di più

Descrivo una risorsa

$ frictionless describe tmp_des.csv --yaml >tmp.yaml


encoding: utf-8
format: csv
hashing: md5
name: tmp_des
path: tmp_des.csv
profile: tabular-data-resource
schema:
  fields:
    - name: Nome
      type: string
    - name: Anni
      type: integer
    - name: Colore
      type: string
    - name: Data
      type: date
scheme: file
encoding: utf-8
format: csv
hashing: md5
name: tmp_des
path: tmp_des.csv
profile: tabular-data-resource
schema:
  fields:
    - name: Nome
      type: string
      description: nome dell'utente
    - name: Anni
      type: integer
      description: età dell'utente
    - name: Colore
      type: string
      description: colore preferito
    - name: Data
      type: date
      description: data di iscrizione
scheme: file

Aggiungo dettagli

In azione ...

Grazie

Andrea Borruso | Associazione onData