#! /usr/bin/perl -w # 12/2004 Laurent FACQ - facq@u-bordeaux-fr (REAUMUR - Université de Bordeaux) ## Programme utilisé pour réaliser des statistiques textes et graphiques ## à partir des données contenue d'une base de données ## (postgresql) ## TODO : parametre range de visualisation <> range de calculs ## TODO : parametre par nom ## ## generation d'une arboresecne web avec raffinement par ... $use= " (/bin/rm -r /tmp/gtssd ; mkdir /tmp/gtssd ; ./pgplot ; cd /tmp/gtssd ; cat *.gnuplot | gnuplot ; xzgv *.png) (/bin/rm -r /tmp/gtssd ; mkdir /tmp/gtssd ; ./pgplot ; cd /tmp/gtssd ; cat *.gnuplot | gnuplot) (cd /tmp/ ; tar -cf - gtssd | gzip -9 > /tmp/gtssd.tgz) "; $use.=$use; ### todo : generer du script 'R' : http://www.r-project.org/index.html ### particionnement avec statistics::descriptive (partition) $dbname= "gtssd"; $dbhost= "localhost"; $debug= 0; use Statistics::Descriptive; # apt-get install libstatistics-descriptive-perl use DBI; # apt-get install libdbi-perl $dbh= DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost","",""); if (!$dbh) { die "DBI:Internal error"; } $outputdir= "/tmp/gtssd"; $table= "survey_2"; $condition_generales = " xratio <> 0 "; unlink("$outputdir/all.pdata"); @sql_defaults= ( WHERE=>$condition_generales, TABLE=>$table, ); @gnuplot_defaults= ( ); @defaults= ( PATH=>$outputdir, ); ################### $req= "SELECT DISTINCT structure FROM $table"; @structures = @{$dbh->selectcol_arrayref($req)}; $req= "SELECT DISTINCT code, answer FROM answers"; $ref= $dbh->selectall_arrayref($req); foreach $row (@{$ref}) { ($code, $ans)= @{$row}; $ans =~ s/[^ -z]/./g; # todo - ne garder que ce qui est imprimable $answers{$code}=$ans; print "$code -> $ans\n" if $debug; } ################### percent(@defaults, TITLE=>"Type de structure ayant repondu", VALUENAME=>"structures", SQL=>[ @sql_defaults, EXP=>'structure', ], ); foreach $structure ( "TOUT",@structures ) { print STDERR "DEBUG : $structure\n"; $suffix= "--$structure"; $comment= $structure; $where = " $condition_generales "; if ($structure ne "TOUT") { $where = " $condition_generales AND structure = ".$dbh->quote($structure)." "; if (defined($answers{$structure})) { $comment.= "- $answers{$structure}"; } } percent(@defaults, TITLE=>"Utilisation d un SSD $comment", VALUENAME=>"ssd$suffix", SQL=>[ @sql_defaults, EXP=>'logicieldedie', WHERE=>$where, ], ); repartition(@defaults, TITLE=>"Repartition du nombre des interlocuteurs $comment", VALUENAME=>"nb-interlocuteurs$suffix", SQL=> [ @sql_defaults, EXP=>'xnbuser', WHERE=>$where, ], STEP=>20, # could be distribution cf frequency_distribution GNUPLOT=>[ @gnuplot_defaults, #####################"""XRANGE=>'[0:500]', ] ); repartition(@defaults, TITLE=>"Repartition du nombre de membres du service $comment", VALUENAME=>"nb-membres-services$suffix", SQL=>[ @sql_defaults, EXP=>'xnbmembres', WHERE=>$where, ], GNUPLOT=>[ @gnuplot_defaults, ], STEP=>1, # could be distribution cf frequency_distribution ); repartition(@defaults, TITLE=>"Repartition du ratio Nb Interlocuteurs par Nb Membres du Service $comment", VALUENAME=>"ratio$suffix", SQL=>[ @sql_defaults, EXP=>'xratio', WHERE=>$where, ], GNUPLOT=>[ @gnuplot_defaults, #######################"XRANGE=>'[0:600]', ], STEP=>10, # could be distribution cf frequency_distribution ); percent(@defaults, TITLE=>"Type de logiciel $comment", VALUENAME=>"typelogiciel$suffix", SQL=>[ @sql_defaults, EXP=>'typelogiciel', WHERE=>" $where AND xoui ", ], ); percent(@defaults, TITLE=>"Soumission de demandes par... $comment", VALUENAME=>"typesoumission-xnon-xnonmais$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon OR xnonmais ) ", ], ); percent(@defaults, TITLE=>"Soumission de demandes par (nbmembre=1)... $comment", VALUENAME=>"typesoumission-xnon-xnonmais-e1$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon OR xnonmais ) AND xnbmembres = 1 ", ], ); percent(@defaults, TITLE=>"Soumission de demandes par (nbmembre>1)... $comment", VALUENAME=>"typesoumission-xnon-xnonmais-s1$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon OR xnonmais ) AND xnbmembres > 1 ", ], ); percent(@defaults, TITLE=>"Soumission de demandes par (nbmembre>2)... $comment", VALUENAME=>"typesoumission-xnon-xnonmais-s2$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon OR xnonmais ) AND xnbmembres > 2 ", ], ); percent(@defaults, TITLE=>"Modification des habitudes $comment", VALUENAME=>"modificationhabitudes$suffix", SQL=>[ @sql_defaults, EXP=>'modificationhabitudes', WHERE=>" $where AND ( xoui ) ", ], ); percent(@defaults, TITLE=>"Pourquoi n'avez vous pas mis en place un tel systeme $comment", VALUENAME=>"pourquoi-non$suffix", SQL=>[ @sql_defaults, EXP=>'pourquoi', WHERE=>" $where AND ( xnon ) ", ], ); percent(@defaults, TITLE=>"Pourquoi avez vous renonce a mettre en place un tel systeme $comment", VALUENAME=>"renonceautiliserssd$suffix", SQL=>[ @sql_defaults, EXP=>'renonceautiliserssd', WHERE=>" $where AND ( xnonmais ) ", ], ); #percent(@defaults, # TITLE=>"Pourquoi avez vous renonce ou n'avez vous pas mis en place un tel systeme", # VALUENAME=>"pourquoi-non-nomais", # SQL=>[ # @sql_defaults, # EXP=>'pourquoi', # WHERE=>" $condition_generales AND ( xnon or xnonmais ) ", # ], # ); percent(@defaults, TITLE=>"Moyen utilises pour soumissionner $comment", VALUENAME=>"typesoumission-xnon$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon ) ", ], ); percent(@defaults, TITLE=>"Existance d'un point d'entree unique $comment", VALUENAME=>"pointentreeunique$suffix", SQL=>[ @sql_defaults, EXP=>'pointentreeunique', WHERE=>" $where AND ( xnon OR xnonmais ) ", ], ); percent(@defaults, TITLE=>"Existance d'un point d'entree unique (nbmembres > 1)$comment", VALUENAME=>"pointentreeunique-s1$suffix", SQL=>[ @sql_defaults, EXP=>'pointentreeunique', WHERE=>" $where AND ( xnon OR xnonmais ) AND xnbmembres > 1 ", ], ); percent(@defaults, TITLE=>"Existance d'un point d'entree unique (nbmembres = 1)$comment", VALUENAME=>"pointentreeunique-e1$suffix", SQL=>[ @sql_defaults, EXP=>'pointentreeunique', WHERE=>" $where AND ( xnon OR xnonmais ) AND xnbmembres = 1 ", ], ); percent(@defaults, TITLE=>"Type de soumission quand existe un point d'entree unique $comment", VALUENAME=>"typesoumission-pour-point-entree-unique$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon or xnonmais ) AND pointentreeunique='Y' ", ], ); percent(@defaults, TITLE=>"Type de soumission quand existe un point d'entree unique (nb membres > 1) $comment", VALUENAME=>"typesoumission-pour-point-entree-unique-s1$suffix", SQL=>[ @sql_defaults, EXP=>'typesoumission', WHERE=>" $where AND ( xnon or xnonmais ) AND pointentreeunique='Y' AND xnbmembres > 1 ", ], ); percent(@defaults, TITLE=>"Duree de mise en place $comment", VALUENAME=>"combientempsmiseenplace$suffix", SQL=>[ @sql_defaults, EXP=>'combientempsmiseenplace', WHERE=>" $where AND ( xoui ) ", ], ); percent(@defaults, TITLE=>"Combien de temps d'utilisation $comment", VALUENAME=>"combiendetempsutilisation$suffix", SQL=>[ @sql_defaults, EXP=>'combiendetempsutilisation', WHERE=>" $where AND ( xoui ) ", ], ); percent(@defaults, TITLE=>"Conseilleriez vous l'utilsiation d'un ssd $comment", VALUENAME=>"conseillessd$suffix", SQL=>[ @sql_defaults, EXP=>'conseillessd', WHERE=>" $where AND ( xoui ) ", ], ); percent(@defaults, TITLE=>"Indice de satisfaction globale $comment", VALUENAME=>"satisfaction$suffix", SQL=>[ @sql_defaults, EXP=>'satisfaction', WHERE=>" $where AND ( xoui ) ", ], ); percent(@defaults, TITLE=>"Polyvalence des membre (> 1) $comment", VALUENAME=>"polyvalence$suffix", SQL=>[ @sql_defaults, EXP=>'polyvalent', WHERE=>" $where AND xnbmembres > 1 ", ], ); percent(@defaults, TITLE=>"Existance de sous equipes (> 1) $comment", VALUENAME=>"sousequipes$suffix", SQL=>[ @sql_defaults, EXP=>'sousequipes', WHERE=>" $where AND xnbmembres > 1 ", ], ); percent(@defaults, TITLE=>"Interlocuteurs permenants - non permanents $comment", VALUENAME=>"typeuserpnp$suffix", SQL=>[ @sql_defaults, EXP=>'typeuserpnp', WHERE=>" $where ", ], ); percent(@defaults, TITLE=>"Type d'interlocuteurs final - correspondant $comment", VALUENAME=>"typeuserfc$suffix", SQL=>[ @sql_defaults, EXP=>'typeuserfc', WHERE=>" $where ", ], ); } # #Voici ce qu'il reste a traiter # # #- Facon de soumettre les demandes A REFAIRE AVEC NON + NOM-MAIS # #- Point d\u2019entree unique (pour non et non-mais) # #- depuis combien de temps logiciel est utilise # #- combien de temps a pris la mise en place # #- est-ce que la mise en place a modifie habitudes des utilisateurs (oui) # #- classer apports logiciels depouiller # #- principales dificultes # #- conseilleriez-vous d\u2019utiliser un SSD ? # #- satisfaction globale # sub percent { my ($table, $titre, $namex, $expx, $cond, $step, $file); my (%param)= @_; my ($p,$sub,$k, $where); my $output=""; foreach $sub ( qw/SQL GNUPLOT/ ) { if (defined($p= $param{$sub})) { $param{$sub}= {}; %{$param{$sub}}= @{$p}; } } if (!defined($param{FILENAME})) { $param{FILENAME}=$param{VALUENAME}; } if (!defined($param{PATH})) { $param{PATH}='/tmp/'; } $file= $param{PATH}."/".$param{FILENAME}; $file=~ s/[^\/a-zA-Z0-9+=-]//g; open(LOG,">$file.log") or die "cannot output in $file..."; my ($row,$val,$i); $where= ""; if (defined($param{SQL}{WHERE})) { $where= " WHERE ( ".$param{SQL}{WHERE}." ) " ; } $exp = $param{SQL}{EXP}; ### utiliser freqneucy distribution (distribution a tranche variables, boite min et boite max) my ($valx) = $exp; my $reqc= "SELECT count(1) as nb " ." FROM $param{SQL}{TABLE} " ." $where "; my ($count)= $dbh->selectrow_array($reqc); print LOG "#".`date`; print LOG "$reqc\n"; my $req= "SELECT $valx as val, " ."count($valx) as nb, round((100::numeric*(count($valx)))/$count,2) as p FROM $param{SQL}{TABLE} " ." $where " ."GROUP BY $valx " ."ORDER BY nb DESC "; print STDERR "DEBUG - Requete : $req\nto $file\n" if $debug; my $ref= $dbh->selectall_arrayref($req); print LOG "$req\n"; ### $output.= "#".`date`; $output.="# $param{TITLE}\n"; $output.="# $reqc\n"; $output.="# $req\n"; foreach $row (@{$ref}) { ($val, $count, $p)= @{$row}; $valexp= ""; if (defined($answers{$val})) { $valexp= $answers{$val}; } $output.="$p% \t $count \t $val [$valexp]\n"; } $output.="\n\n"; open(OUT,">$file.pdata") or die "cannot output in $file..."; print OUT $output; close(OUT); open(OUT,">>$param{PATH}/all.pdata") or die "cannot output in $file..."; print OUT $output; close(OUT); } sub repartition { my ($table, $titre, $namex, $expx, $cond, $step, $file); my (%param)= @_; my ($p,$sub,$k, $where, $total); foreach $sub ( qw/SQL GNUPLOT/ ) { if (defined($p= $param{$sub})) { $param{$sub}= {}; %{$param{$sub}}= @{$p}; } } if (!defined($param{FILENAME})) { $param{FILENAME}=$param{VALUENAME}; } if (!defined($param{PATH})) { $param{PATH}='/tmp/'; } $file= $param{PATH}."/".$param{FILENAME}; $file=~ s/[^\/a-zA-Z0-9+=-]//g; open(LOG,">$file.log") or die "cannot output in $file..."; my ($row,$val,$i); $where= ""; if (defined($param{SQL}{WHERE})) { $where= " WHERE ( ".$param{SQL}{WHERE}." ) " ; } $step= $param{STEP}; $exp = $param{SQL}{EXP}; my $valx="$step/2+($step)*round((($exp)/($step))::numeric,0)"; ### utiliser freqneucy distribution (distribution a tranche variables, boite min et boite max) my $req= "SELECT $valx as val, " ."count($valx) as nb FROM $param{SQL}{TABLE} " ." $where " ."GROUP BY $valx "; print STDERR "DEBUG - Requete : $req\nto $file\n" if $debug; print LOG "#".`date`; print LOG "$req\n"; my $ref= $dbh->selectall_arrayref($req); my $stat= Statistics::Descriptive::Full->new(); ### open(OUT,">$file.data") or die "cannot output in $file..."; print OUT "#".`date`; $total= 0; foreach $row (@{$ref}) { ($val, $count)= @{$row}; $total += $count; print OUT "$val $count\n"; foreach $i (1..$count) { $stat->add_data($val); # "x $count); } } close(OUT); ### $centilrange1= $stat->percentile(10)-1; $centilrange2= $stat->percentile(90)+1; $centilrange= "[$centilrange1:$centilrange2]"; open(GNUPLOT,">$file.gnuplot") or die "cannot output in $file..."; open(TEXT,">$file.text") or die "cannot output in $file..."; print GNUPLOT "reset \n"; print GNUPLOT "set terminal png large \n"; print GNUPLOT "set output \"$file.png\"\n"; print GNUPLOT "set xlabel \" $param{VALUENAME} \" \n"; print GNUPLOT "set ylabel \" nb réponses \" \n"; print GNUPLOT "set title \"$centilrange ".$param{TITLE}." (/$step)\" \n"; foreach $k (keys %{$param{GNUPLOT}}) { print GNUPLOT "set ".lc($k)." ".$param{GNUPLOT}{$k}."\n"; } print GNUPLOT "set xrange $centilrange\n"; # print GNUPLOT "plot '"."$file.data"."' with impulses \n"; # print GNUPLOT "plot '"."$file.data"."' with linespoints \n"; # print GNUPLOT "plot '"."$file.data"."' with boxes \n"; # print GNUPLOT "plot '"."$file.data"."' title \"nb $param{VALUENAME}\" with impulses \n"; print GNUPLOT "plot '"."$file.data"."' title \"\" with impulses \n"; #print GNUPLOT "pause mouse \" attente return \" \n"; #print GNUPLOT "pause 100 \" attente return \" \n"; print TEXT "$param{TITLE} $centilrange\n"; print TEXT "Nombre de reposnes : \t $total\n"; print TEXT "Deviation Standard : \t ".$stat->standard_deviation()." \n"; print TEXT "Centil 25 : \t ".$stat->percentile(25)." \n"; print TEXT "Centil 75 : \t ".$stat->percentile(75)." \n"; print TEXT "Mediane : \t ".$stat->median()." \n"; print TEXT "Mode : \t ".$stat->mode()." \n"; print TEXT "Moyenne : \t ".$stat->mean()." \n"; print TEXT "Nombre : \t ".$stat->count()." \n"; print TEXT "Min : \t ".$stat->min()." \n"; print TEXT "Max : \t ".$stat->max()." \n"; close(GNUPLOT); close(TEXT); close(LOG); }