05 marzo 2010

R in PostgreSQL

L'integrazione di R con i DBMS è un aspetto molto importante per la realizzazione di soluzioni analitiche in questo linguaggio. Se si lavora in ambito industriale, ad esempio, i dati saranno raccolti in un database. Quindi, sarà necessario sviluppare un'interfaccia "facile" al motore di calcolo e permettere all'utente di interrogare i dati, sia per estrarre informazioni "semplici" (in tal caso R dovrebbe essere superfluo), sia per applicare una qualche forma di sintesi. Se per quest'ultimo tipo di elaborazione, le funzioni di aggregazione previste nel db non fossero sufficienti, è possibile ricorrere ad R. Una prima possibilità, sicuramente molto più diffusa, è quella di lavorare importando i dati in R ed eseguendo, direttamente in tale ambiente, le necessarie elaborazioni. Tale tipo di approccio, ad esempio, lo si realizza facilmente mediante il package RODBC.
Esiste tuttavia un'altra possibilità che, in base ad una mia personale sensazione, è poco conosciuta. Nell'universo dei DBMS, esiste ed è molto diffuso PostgreSQL . Per tale tipo di database, è prevista la possibilità di utilizzare un particolare linguaggio procedurale, ossia PL/R, che permette di scrivere (ed utilizzare) direttamente in PostgreSQL, funzioni in linguaggio R (in realtà esiste anche la possibilità di lavorare in R mediante RPgSQL, ma spero di dedicarci un post a parte). Quindi, saranno disponibili tutte le normali funzioni già previste in R, nelle varie librerie, così come sarà possibile sviluppare nuove funzioni di PostrgreSQL, utilizzando la sintassi di R.
Per l'utilizzo di tali modalità, ovviamente, è necessario avere una certa conoscenza di questo database, oltre che una certa familiarità con R. Per le problematiche di installazione (in particolare, in ambiente Windows) ed utilizzo, in generale, si rimanda ai siti:
Oltre a fare questa segnalazione, quindi, intendo riportare degli esempi utili ad evidenziare le potenzialità di tale modalità di sviluppo.

Immaginiamo di progettare, in ambito industriale, un database che raccoglie dati sulla produzione di semilavorati in un centro siderurgico, ad esempio dei tubi di acciaio. Periodicamente, a campione, viene misurata e registrata la circonferenza esatta di tali prodotti che, ovviamente, deve rispettare determinati livelli di tolleranza prestabiliti. In tale processo industriale, quindi, ci si aspetta un "errore" nella produzione, ossia degli scostamenti dalla circonferenza media prevista. Per controlloare questo aspetto, ad esempio, si cercherà di testare l'ipotesi di normalità dei dati, quindi la casualità degli scarti. Nell'esempio che propongo successivamente, quindi, vado proprio ad eseguire un test statistico sulla normalità dei dati direttamente nel database, in maniera "nativa". A mio parere, questo è un risultato eccezionale! Non mi sembra esistano possibilità analoghe in altri DBMS!
Non è superfluo evidenziare che si tratta solo di un esempio! Nell'ambito del controllo statistico della qualità, il controllo della produzione è realizzato mediante processi più complessi.

Quindi, riepilogando, è sufficiente crare un'apposita funzione in PostgreSQL, mediante il seguente codice:

CREATE OR REPLACE FUNCTION testNormality(tb text, col text)
RETURNS double precision AS
'
sql<-paste("select", col, "from", tb)
rs<-pg.spi.exec(sql)
shapiro.test(rs[,1])$p.value
'
LANGUAGE 'plr';

In generale, in PostgreSQL è possibile utilizzare diversi estensioni di linguaggio procedurale (come pgSQL, Python, Java ...), che rendono altamente personalizzabili le funzioni presenti nel database. Nello specifico, qui stiamo usando il linguaggio PL/R che, appunto, mi permette di scrivere in R. La documentazione ufficiale la trovate qui. In particolare, si noti che tra gli apici va riportato il codice R, che verrà eseguito alla chiamata della funzione.
Nel nostro caso, quindi, sto definendo la funzione testNormality che prende in input due parametri di tipo testo: il nome di una tabella (tb) e il nome di un campo di quest'ultima (col). Tali informazioni vengono "passate" ad R in cui creo la stringa sql che, appunto è la query in linguaggio SQL:

SELECT col FROM tb;