Funzioni definite dall’utente¶
In pTabs è possibile definire delle proprie funzioni [1] che si comportano in modo analogo ai comandi predefiniti. Una nuova funzione può essere utilizzata per eseguire una serie di istruzioni di pTabs o per memorizzare valori e dati da utilizzare nello script.
Una funzione corrisponde a quello che in altri software viene definito come macro.
Una funzione può ricevere dei parametri che possono condizionare la sua esecuzione o possono essere elaborati dalla funzione.
Una funzione che restituisce uno o più valori può essere utilizzata come argomento di un’altra istruzione pTabs.
Avvertimento
Attenzione a non utilizzare come nomi delle proprie funzioni e variabili nomi di istruzioni di pTabs. In tal caso la nuova funzione o variabile sovrascriverà quella di pTabs, che non sarà più visibile.
Funzioni e variabili interne al report¶
Per rendere più fluida la scrittura di uno script ed evitare ripetizioni, può essere utile definire delle variabili o delle proprie funzioni all’interno di un report.
Le funzioni vengono definite con l’istruzione def.
Una variabile viene creata semplicemente assegnando un valore a un identificatore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | report = ptabs.new do
...
pesi = [0.25, 0.37, 0.75, 1.5, 2.5, 3, 3.5, 4, 5]
def my_tab(n, root)
ord "#{root}_#{n}"
w :legend, pesi
end
end
(1..10).rep {|i| my_tab i, :q45}
(1..15).rep {|i| my_tab i, :q47}
(1..18).rep {|i| my_tab i, :q52}
...
end
|
La variabile pesi e la funzione my_tab saranno visibili solo all’interno del blocco ptabs.new ... end.
Nota
Questo tipo di sintassi è utilizzabile solo se la definizione e l’utilizzo della funzione o della variabile avviene all’interno dello stesso report.
Funzioni e variabili globali¶
Un modo più proficuo di scrivere le proprie funzioni, comporta la possibilità di riutilizzarle in differenti report dello stesso lavoro o tra diversi lavori.
Per definire tali tipi di funzioni e variabili è necessario utilizzare una sintassi specifica. [2]
Definizione¶
Le nuove funzioni possono essere definite con l’istruzione defpfun per le funzioni da usare al di fuori del report e deffun per le funzioni da usare all’interno del blocco del report (ptabs.new ... end). Il nome della funzione deve essere un simbolo.
1 2 3 4 5 6 7 | defpfun :my_function_1 do |argomenti|
# corpo della funzione
end
deffun :my_function_2 do |argomenti|
# corpo della funzione
end
|
Le variabili possono essere definite con l’istruzione defpvar per le variabili da usare al di fuori del report e defvar per le funzioni da usare all’interno del blocco del report (ptabs.new ... end). Il nome della variabile deve essere un simbolo.
1 2 3 4 5 | defpvar :my_var_1 => valore
defvar :my_var_2 => valore
defvar :my_var_3 => valore, :my_var_4 => valore, :my_var_5 => valore
defvar my_var_6: valore, my_var_7: valore
|
nome: valore è una variante sintattica equivalente a :nome => valore.
Un’unica istruzione defpvar o defvar permette di creare più variabili contemporaneamente.
Collocazione¶
Questie funzioni e variabili possono essere definite ovunque: nello stesso script o in file esterni.
I file esterni devono essere file Ruby con estensione .rb e possono essere caricati nello script con la sintassi:
1 | require 'my_filename' # senza estensione
|
Se il file risiede nella stessa cartella dello script, verrà trovato senza la necessità di specificare il percorso.
user_functions.rb¶
La cartella user [3] contiene lo stub file user_function.rb in cui è possibile aggiungere delle proprie funzioni di uso ricorrente. Questo file viene automaticamente caricato in ogni scipt di pTabs.
E’ anche possibile inserire nella cartella user ulteriori file Ruby. Questi file dovranno essere caricati esplicitamente nello script con l’istruzione require, ma non è necessario specificarne il percorso.
Per fare in modo che vengano caricati automaticamente, inserire l’istruzione require direttamente nel file user_functions.rb.
Nel caso si voglia caricare un file presente in un percorso differente, magari di rete, aggiungere il percorso nell’istruzione require, ricordandosi di utilizzare il carattere / e non \:
1 | require 'x:/my/path/my_filename'
|
defpfun e defpvar¶
defpfun e defpvar devono essere usati per generare funzioni e variabili che lavorano esternamente alla definizione del report e che hanno bisogno di far riferimento all’oggetto ptabs. Le nuove funzioni e variabili saranno disponibili con la sintassi: ptabs.my_function_name.
Esempio: esecuzione parametrizzata di un report¶
Un report viene definito e poi eseguito due volte con parametri differenti.
1 2 3 4 5 6 7 8 9 10 11 12 13 | defpfun :myrep do |rep_name, caption, data_file|
report = ptabs.new(filename) do
title caption
spss.open data_file
...
end
report.render :html
end
ptabs.myrep "rep001", "Report XXX", "dat001"
ptabs.myrep "rep002", "Report YYY", "dat002"
|
Esempio: generazione output¶
La funzione che esegue i metodi render desiderati del report, permettendo di scegliere se produrre tutti gli output (:test) o solo l’html (:all) .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | defpfun :print do |report, mode=:test|
report.render :html
if mode == :all
report.render :pdf
report.render :xls, :single_panel => true,
:sheets => { "VA %" => [:count, :rowpct, :colpct, :mresp, :base, :mean, :sd, :se, :mtest],
"%" => [ :rowpct, :colpct, :mresp, :base, :mean ],
"VA" => [:count, :mresp, :base, :mean ] }
report.render :db
end
end
report = ptabs.new do
...
end
ptabs.print report
|
deffun e defvar¶
deffun e defvar devono essere usati per generare funzioni e variabili che devono essere eseguite all’inteno di un report (all’interno del blocco ptabs.new ... end) per esempio funzioni che definiscono tavole. Le nuove funzioni e variabili saranno direttamente disponibili all’interno di un report con la sintassi: my_function_name.
Esempio: tabella personalizzata¶
Si definisce una nuova istruzione che genera un tipo specifico di tavola da usarsi per variabili con scala a 10 punti più non risponde.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | deffun :ord_net do |varname, caption|
ord varname, caption do
net "NEGATIVO" => 1..5, "POSITIVO" => 6..10, "NON RISPONDE" => 11
w :legend, "( # ) *", 1,2,3,4,5,6,7,8,9,10,:na
hide 14
end
end
report = ptabs.new do
...
ord_net :v25, "Tabella D25 - ..."
...
end
|
Esempio: pesi di uso ricorrente¶
Una variabile può servire semplicemente per memorizzare e poi restituire dei valori (dati o strutture di dati) da utilizzare nello script.
Nell’esempio, vengono definiti dei pesi da utilizzare per una specifica tipologia di domanda.
1 2 3 4 5 6 | defvar :my_weights => [0.25, 0.37, 0.75, 1.5, 2.5, 3, 3.5, 4, 5]
# -- nel report
ord ... do
w :legend, my_weights
end
|
Il valore memorizzato nella variabile non è un semplice numero, ma è un vettore contenete più elementi. La variabile viene usata, nell’esempio, come argomento del sottocomando w.
Esempio: template del titolo della tabella¶
Si definisce un template personalizzato da usare nei titoli delle tabelle.
1 2 3 4 5 6 | deffun :my_title(n, title, subtitle=nil)
"Dom.#{n} - #{title}" + (subtitle.empty? ? "" : "\n -*- #{subtitle} -*-")
end
# -- nel report
cat :d1, my_title(1, "Titolo", "Sottotitolo")
|
Questa funzione non esegue nessuna istruzione pTabs, ma restituisce [4] semplicemente una stringa di testo costruita a partire dai parametri di input.
La funzione viene usata, nell’esempio, come argomento dell’istruzione cat al posto del titolo.
Esempio: libreria di ponderazioni¶
L’esempio seguente illustra un semplice metodo per creare una libreria contenente i marginali e le numerosità degli universi da utilizzare nelle ponderazioni.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # -- file: users/universi.rb
# INDIVIDUI >= 18 ANNI
defvar :uni_18_n => 47_431_000,
:uni_18 => {
:sesso => [47.8, 52.2],
:ampc => [18.6, 29.2, 17.4, 1.0, 23.8],
:istr => [28.0, 36.3, 28.4, 7.3],
:area => [10.7, 16.1, 11.8, 7.3, 13.4, 9.0, 18.9, 12.7],
}
# FAMIGLIE
defvar :uni_fam_n => 21_810_000,
:uni_fam => {
:area => [11.8, 16.8, 11.8, 7.6, 13.0, 9.1, 17.5, 12.4],
:ncomp => [24.9, 27.1, 21.6, 18.9, 7.6],
:etacap => [11.9, 18.9, 18.5, 17.9, 32.8],
}
# -- nello stesso script o meglio in 'user_functions.rb'
require 'universi'
# -- nello script
rake :names => [:ipf, :esp],
:counts => [uni_18_n],
:population => uni_18
|
47_431_000 viene letto come un semplice numero intero. Nei numeri, il carattere sottolineato _ può essere utilizzato come separatore delle migliaia per facilitare la lettura.
Callbacks¶
I callbacks sono funzioni che vengono richiamate durante la generazione dei report. Per comportamento predefinito non svolgono nessuna azione, ma l’utente può ridefinirle per inserire dei comportamenti specifici.
Funzioni dell’oggetto report¶
Queste funzioni vanno ridefinite con deffun.
render_title¶
render_title permette di modificare il titolo della tabella.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Segnatura
render_title(title, index)
# Esempio di ridefinizione:
# - aggiunge "TAB.# - " e mette in maiuscolo il titolo della tavola
deffun :render_title do |title, index|
"TAB.#{index} - "+title.upcase
end
# Esempio di ridefinizione:
# - elimina "V###_#: Question ###_#: " dal titolo della tavola
deffun :render_title do |title, index|
title.gsub(/V[\d_]+:\sQuestion\s\d+:\s?/,'').strip
end
|
skip_variable¶
skip_variable permette di valutare se escludere o meno una variabile/set di variabili dal topline o dalla procedura autotab. Viene eseguito prima del calcolo delle statistiche.
variable è un oggetto PTables::VariableInfo (vedere info).
1 2 3 4 5 6 7 8 9 10 11 12 | # Segnatura
skip_variable(variable)
# Esempio di ridefinizione:
# - la variabile compare nel topline solo se il metodo restituisce false
deffun :skip_variable do |variable|
return true if variable.alpha?
return true if %w(intnr inttime scrcnt internr stime).include?(variable.name)
return true if variable.label =~ /^INTERVISTATORE:/i
return true if variable.levels.include?("CATI")
false
end
|
skip_summary¶
skip_summary permette di valutare se escludere o meno una variabile/set di variabili dall’output del topline. Viene eseguito dopo aver calcolato le statistiche.
summary è un oggetto PTables::TopLine::Summary.
Metodi dell’oggetto Summary:
- varname: restituisce il nome della variabile o la radice del nome del set di variabili
- varnames: restituisce un Array con i nomi delle variabili
- caption: restituisce il titolo
- labels: restituisce un Array con le etichette
- id: restituisce il progressivo della tabella
- numeric?: restituisce true se la variabile è numerica
- single?: restituisce true se la variabile è singola
- multi?: restituisce true se la variabile è multipla
- base: restituisce la base
1 2 3 4 5 6 7 8 9 | # Segnatura
skip_summary(summary)
# Esempio di ridefinizione:
# - la variabile compare nel topline solo se il metodo restituisce false
deffun :skip_summary do |summary|
return true if summary.base < 10
false
end
|
auto_tab¶
auto_tab viene chiamato dalla procedura autotab per produrre automaticamente tutte le tabelle per un elenco di variabili o, se non specificato, per tutte le variabili del file di dati.
Di auto_tab viene già fornita un’implementazione completa, ma è possibile personalizzare la procedura ridefinendo la funzione.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # Segnatura
auto_tab(variables_list)
# Implementazione di default
deffun :auto_tab do |variables|
i = 0
variables.each do |var| # cicla sulle variabili (e gli eventuali set)
inf = info var # recupera le informazioni sulla variabile
next if skip_variable(inf) # salta alla variabile successiva se non è da tabulare
next if inf.alpha? # salta alla variabile successiva se è una variabile alfanumerica
if inf.set? # se è un set di variabili
if inf.multi? # se è un set multiplo
md var.vars, "Tabella #{i+=1} - [$vn()] #{var.title}" # tabella md
else # altri set
scale var.vars, "Tabella #{i+=1} - [$vn()] #{var.title}" # tabella scale riassuntiva
var.vars.each do |v| # cicla sulle variabili del set
ord v, "Tabella #{i+=1} - [$vn()] $vl()" # tabella ord di dettaglio
end
end
elsif inf.factor? # se variabile factor
cat var, "Tabella #{i+=1} - [$vn()] $vl()" # tabella cat
elsif inf.numeric? # se variabile numerica
scale var, "Tabella #{i+=1} - [$vn()] $vl()" # tabella scale
end
end
end
|
Simboli per test significatività¶
Tre funzioni definiscono l’elenco di simboli utilizzati per identificare le colonne nei test di significatività.
Le funzioni devono restituire un Hash con le chiavi :header e markers:
- :header: simboli da utilizzare per le intestazioni delle colonne
- :markers: simboli da utilizzare nelle celle
markers_1_level
Simboli per pairwise comparisons con 1 solo livello di significatività.
1 2 3 4 5 6 7 8 | # (implementazione di default)
deffun :markers_1_level do
markers = ('a'..'z').to_a + %w(* $ & @ # ^ = + - !) + ('A'..'Z').to_a
{
:header => markers,
:markers => markers
}
end
|
markers_2_level
Simboli per pairwise comparisons con 2 livelli di significatività. markers contiene un solo vettore di simboli. Per il secondo livello di significatività i simboli vengono convertiti in maiuscolo.
1 2 3 4 5 6 7 8 | # (implementazione di default)
deffun :markers_2_level do
markers = (['']+(1..9).to_a).map{|i| ('a'..'z').to_a.map{|x| "#{x}#{i}"}}.flatten
{
:header => markers,
:markers => markers
}
end
|
markers_9_level
Simboli per pairwise comparisons fino a 9 livelli di significatività. markers è un vettore che contiene nove vettori di simboli, uno per ogni livello di significatività.
1 2 3 4 5 6 7 8 | # (implementazione di default)
deffun :markers_9_level do
markers = ('a'..'z').to_a
{
:header => markers,
:markers => ((1..9).to_a).map{|i| markers.map{|x| "#{x}#{i}"}}
}
end
|
Funzioni dell’oggetto ptabs¶
Queste funzioni vanno ridefinite con defpfun.
before_report¶
before_report viene eseguito prima della definizione del report.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Segnatura
before_report(ptabs)
# Esempio di ridefinizione:
# - scarica il file di dati da un sito ftp
defpfun :before_report do |ptabs|
require 'net/ftp'
ftp - Net::FTP.new 'ftp.name.com'
ftp.login "user", "password"
ftp.chdir "/path/ftp"
ftp.getbinaryfile "source.dat", "target.dat"
ftp.close
end
|
after_report¶
after_report viene eseguito al termine della definizione del report.
1 2 | # Segnatura
after_report(report)
|
before_exit¶
before_exit viene eseguito prima del termine di pTabs.
1 2 3 4 5 6 7 8 | # Segnatura
before_exit(ptabs)
# Esempio di ridefinizione:
# - copia il report prodotto
defpfun :before_exit do |ptabs|
system "copy report.pdf x:\\Public"
end
|
Note
[1] | Tecnicamente in Ruby, come in genere nei linguaggi a oggetti, si tratta di metodi. Qui useremo il termine di funzioni in senso lato. |
[2] | Tecnicamente defpfun, defpvar, deffun e defvar generano dei nuovi metodi all’interno dei moduli User::Ptabs e User::Report. defpvar è un alias si defpfun e defvar è un alias si deffun |
[3] | La cartella user si trova nel percorso di installazione di pTabs. Una nuova installazione non ne sovrascrive il contenuto. Nel caso sia stata definita la variabile d’ambiente PTABS_USER la cartella user non è più attiva e bisogna utilizzare al suo posto quella definita in PTABS_USER. In tal caso è necessario copiare il file user_functions.rb. |
[4] | Qualsiasi funzione in Ruby restituisce un valore: la variabile o il valore presente nell’ultima riga del corpo della funzione o comunque l’ultima espressione valutata. |