Benfordsches Gesetz oder: Google mit SAS aufrufen

Letzte Woche hat mich ein Freund auf das Benfordsche Gesetz hingewiesen. Es besagt, sehr vereinfacht, dass "in der Natur" Zahlen, die mit 1 beginnen, häufiger vorkommen, als Zahlen, die mit 2 beginnen und so weiter (wenn die Anzahl Stellen die gleiche ist). Am wenigsten häufig kommen Zahlen vor, die mit 9 beginnen. Das hat mir zuerst nicht eingeleuchtet, eigentlich dachte ich, alle Anfangsziffern seien gleich wahrscheinlich. Aber anscheinden wurden mit Hilfe dieses Gesetzes sogar die Bilanzskandale bei Enron und Worldcom aufgedeckt: die Bilanzfälscher hatten Zahlen produziert, die nicht dem Benforschen Muster folgten.

Das Nette an diesem Gesetz ist, dass man es recht einfach empirisch überprüfen kann, indem man bei Google nach verschiedenen Zahlen suchen lässt und abliest, wie oft diese gefunden werden. Zahlen, die mit eins beginnen, kommen immer am häufigsten vor. Mich hat interessiert, wie man das mit SAS automatisieren kann. Das beiliegende SAS-Programm ruft über FILENAME URL Google auf und ermittelt in der von Google gelieferten Ergbnisseite, wie oft eine bestimmte Zahl gefunden wurde. Dabei werden reguläre Perl-Ausdrücke verwendet. Das Ergebnis wird als Diagramm ausgegeben.

Ich danke Herrn Dr. Stefan Hagl von der Acxiom Deutschland GmbH für die Erlaubnis, seine anschauliche Darstellung des Benfordschen Gesetzes zu veröffentlichen.

Das SAS-Programm und dessen Ergebnis stehen auch zum Download zur Verfügung.

/* ermitteln, wie oft Google einen bestimmten String findet */
%macro GoogleCount (
   string        
/* Suchstring */
  
,mvar=count    /* Rückgabe in Makrovariable &count */
);

/* Zugriff auf Google */
filename google url "http://www.google.de/search?hl=de%str(&)q=&string";

data _null_;
   if _n_=
1 then do;
      
/* Suchmuster: 'Ergebnisse 1 - 10 von ungefähr xxxxxx für ...' */
      
prx = prxparse ('/Ergebnisse .+ von ungef.+hr <b>(\S+)<\/b> f.+r/');
      retain prx;
   end;
   infile google length=len lrecl=
32767 length=reclen;
   input rec
$varying32767. reclen;
   if prxmatch (prx, rec) then do;
      call prxposn (prx,
1, pos, len);
      s = substr (rec, pos, len);
      call symputx (
"&mvar", input (s, commax32.));  
   end;
run;

%mend GoogleCount;


/* Häufigkeiten für Zahlen über Google ermitteln */
%macro benford (
   digits=
5    /* wie viele Stellen sollen die Zahlen haben? */
  
,repeat=10   /* wie oft sollen alle Anfangsziffern 1..9 durchprobiert werden? */
);

%local first i number count digit;

proc sql noprint;
   create table benford (first int, number int, count int);
quit;

%do i=1 %to &repeat;
   
%do first=1 %to 9;
      
%let number=&first;
      
%do digit=1 %to %eval(&digits-1);
         
%let number=&number%sysfunc(floor(%sysevalf(%sysfunc(uniform (0))*10)));
      
%end;
      
%let count=0;
      %GoogleCount (&number);
      proc sql;
         insert into benford values (&first, &number, &count);
      quit;
   
%end;
%end;

ods pdf file=
'c:\temp\benford.pdf';

title height =
20pt "Benfordsches Gesetz überprüfen auf Google";
title2
"&digits-stellige Zahlen, &repeat Durchläufe";
footnote
"www.redscope.org";
goptions ftext=
"Helvetica";

proc means data=benford mean median std min max ;
   class first;
   var count;
run;

proc gchart data=benford;
   hbar first / sumvar=count type=mean mean discrete;
run;
quit;

ods pdf close;

%mend benford;

%benford (digits=
5, repeat=10);