#Klooienmetcomputers

Data-analyse!

Arnout van Kempen over rommelen in een digitale wereld.

Heeft al dat gerommel nou nog ooit enig nut? Ik dacht het wel. En om dat te laten zien gaan we echte data-analyse doen dit keer. Heel simpele, dat wel, maar toch echte data-analyse.

Stel dat we van een tekst willen weten hoe vaak een opgegeven letter in die tekst voorkomt. De tekst is opgeslagen in een bestand, maar we weten nog niet welke letter we gaan tellen, en ook niet in welk bestand die letter geteld moet worden. Om het nog wat lastiger te maken, tellen we hoofdletters en kleine letters mee. Verder willen we graag de tekst kunnen meelezen met de computer, ofwel het bestand moet in beeld worden gebracht. En dan graag een leesbare pagina tegelijk. Of, alternatief, de output moet naar een printer worden gestuurd, zodat we alles nog eens op papier kunnen nalezen.

Om dat te bereiken gaan we een reeks nieuwe dingen doen, in C, maar ook in de shell.

Stap 1 wordt het meegeven van een naam aan ons programma. Tot nu toe hebben we steeds a.out gebruikt, omdat dat de standaardnaam is die gcc meegeeft. Dat is prima om mee te testen, maar een beetje raar voor ‘echte’ programma’s. Een normalere naam meegeven is heel simpel:

gcc broncode.c -o naam

compileert de broncode uit broncode.c en geeft het programma de naam naam.

Stap 2 gaan we gebruiken bij het uitvoeren van ons programma en heet piping. Het is een faciliteit die in Linux, Windows en MacOS gebruikt kunnen worden. Met het | teken kan de output van het ene programma als input voor een ander programma worden gebruikt. Stel dat we ons programma analyse noemen, dan hebben we drie mogelijkheden:

analyse geeft de output zonder meer op het scherm.
analyse | more geeft de output pagina voor pagina op het scherm
analyse | lpr stuurt de output naar de standaard printer van het systeem.

Stap 3 is het gebruik van argumenten. We willen immers niet alleen ons programma starten, we willen ook meegeven welk bestand geanalyseerd moet worden, en naar welke letter gezocht moet worden. Het gebruik moet dus analyse test.txt a worden bijvoorbeeld, waarbij test.txt het te analyseren bestand is, en a de letter waarop gezocht moet worden.

Om dit te bereiken geven we aan de main() functie twee argumenten mee: int argc en char*argv[]. Argc is een teller voor het aantal argumenten (minimaal 1, want de programma-naam zelf telt ook mee) en argv[] is een array van strings, met per argument een element. In ons voorbeeld krijg je dus:

argv[0]==“./analyse”
argv[1]==“test.txt”
argv[2]==“a”

Let op dat het strings zijn, en dus dubbele haken. Als je het character ‘a’ zoekt in het tweede argument, dan is dat het eerste element van die string, dus

argv[2]==“a”
argv[2][0]==‘a’

Stap 4 is het openen van een bestand. In C werkt dat via een pointer naar het type FILE en de functie fopen(). Deze functie heeft twee strings nodig, een met de naam van het bestand en een met de wijze van openen. Voor ons doel wordt dat “lezen” en daarvoor is de string “r”, van read, nodig. Dat wordt dus

FILE *fp;
fp=fopen(argv[1],”r”);

Als het openen van het bestand niet lukt krijgt fp de waarde NULL.

Om dit allemaal te laten werken zullen we flink wat fouten van de gebruiker moeten ondervangen. Klopt het aantal argumenten wel? Zijn de argumenten een bestaand bestand en een letter? Als daar iets fout gaat moeten we stoppen met een duidelijke foutmelding. Als we zowel hoofdletters als kleine letters willen accepteren, is het nu handig het argv[2] te converteren naar een hoofdletter (of een kleine letter, maar maak een keuze). Gebruik makend van het feit dat in de ASCII-tabel de kleine letters precies 32 posities verder liggen ten opzichte van de hoofdletters, en de Z bij 90 ligt, kan dat bijvoorbeeld met

letter = argv[2][0]>90 ? argv[2][0]-32 : argv[2][0];

Stap 5 wordt het feitelijke uitlezen van het bestand en het tellen van de gevraagde letter. Hiervoor kan fgetc() gebruikt worden. Deze functie leest simpelweg 1 character uit de aangegeven file en geeft die terug als int. Als de hele file is gelezen geeft de functie een “end of file”-code, gedefinieerd als EOF. Je kan op EOF testen, of je gebruikt de functie feof() die test of als laatste een EOF is gelezen. De code om het hele bestand te lezen, een teller bij te laten houden of de gezochte letter is gevonden en het bestand af te drukken, kan er dan zo uitzien:

do
{
     teken=fgetc(fp);
     if(teken!=EOF)
     {
           printf(“%c”,teken);
           if((teken>90 ? teken-32 : teken)==letter) teller++;
     }
} while(!feof(fp));
fclose(fp);

en hierna heeft teller het aantal maal dat letter in het bestand voorkwam.

Stap 6 is de fantasie op dit alles los te laten. Met de kennis van de afgelopen 23 afleveringen kan in principe heel wat data-analyse geprogrammeerd worden, waarmee alle mogelijke bestanden van klanten onderzocht kunnen worden op, in feite, alles wat je maar bedenken kan.
Voorraadbestanden, ouderdomsanalyses, grootboeken, debiteurenlijsten, memoriaalboekingen, in feite alles dat je maar in een administratie kan vinden, het zijn allemaal gewone tekstbestanden, klaar voor analyse.

Maar ook log-bestanden waarin gebruikersactiviteiten zijn opgenomen. Contracten. E-mail-boxen. Projectplanningen. Allemaal bestanden die je kan inlezen.

Een tijdje terug bekeken we warchalking en de mogelijkheden van wifi. Alles wat door de lucht gaat bij je klant kan je uitlezen en in een bestand plaatsen, om vervolgens te analyseren.

Vraag je nooit af “kan dat wel?”, maar bedenk wat je wil weten en programmeer het.

Op GitHub staat een compleet programma zoals hiervoor besproken en een bestandje test.txt voor wie het veilig wil uitproberen. Als je het goed doet, zal het antwoord altijd 2 zijn.

Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op www.github.com en zoek naar Abmvk/kmc. Het account Abmvk volgen kan ook. Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren.

Arnout van Kempen di CCO CISA is directeur compliance & risk bij aaff, de fusieorganisatie van Alfa en ABAB. Hij schrijft op persoonlijke titel.

Gerelateerd

7 reacties

Ron Heinen

@Louren van Garderen

Dank voor de reactie.

De stappen Data-Extractie en Data-Transformatie met C in het ETL-proces uit NBA-handreiking 1141 moet je breed zien.

Hier kan allerlei input voor gebruikt worden, niet alleen data uit een "database connectie".

Dan heeft C zeer veel mogelijkheden, zie bijvoorbeeld het voorbeeld uit het artikel: "Alles wat door de lucht gaat bij je klant kan je uitlezen en in een bestand plaatsen, om vervolgens te analyseren."

Vanaf de stap "Importeren Data analyse tool" in het ETL-proces kun je bijvoorbeeld R gaan gebruiken.

Arnout van Kempen

@Louren, lijkt me prachtig! Gaan we doen

Louren van Garderen

Leuk dat jullie reageren!

@Arnout
C/C++ is prachtig, zeker als je low level technieken wil snappen en laten zien. Maar ingewikkeld! Kudos dat jij dit überhaupt als zelf-benoemd leek hebt opgepakt.

Voor de "citizen data scientists", of amateurs in jouw woorden, is 't IMHO te ingewikkeld. Ik krijg nog nachtmerries van de colleges 'malloc' in CS50. :)

Zullen we samen eens bijv. een memoriaalanalyse in Python schrijven, voor #klooienmetcomputers? Lijkt me leuk!

@Ron Heinen
Good gatch, ik ga dat nog eens teruglezen in 1141. Ben het ook vaak oneens met de handreiking hoor! Neemt niet weg dat het een fantastisch startpunt geweest is, en de principes zijn valide.

Mijn mening: elke stap in het proces, van database connectie tot rapport, kan veel beter in Python/R/Alteryx dan C. C is hiervoor te foutgevoelig en instabiel. Maar vooral veel te tijdrovend.

In de programmeerwereld wordt vaak gezegd: C is (technisch) efficienter dan Python. Maar ik huur liever een extra server, dan een extra developer team.

Ron Heinen

@Louren van Garderen

Als we kijken naar de NBA-handreiking 1141, zie bijvoorbeeld

https://www.accountant.nl/nieuws/2023/9/accountants-worstelen-met-overstap-naar-datagestuurde-processen/

dan is de taal C handig in de eerste stappen van de data-analyse bijvoorbeeld bij data-extractie en R is handig in de latere stappen van de data-analyse.

Arnout van Kempen

Zeker, Python en R zijn voor sommige (veel?) mensen makkelijker op het oog. Toch kies ik voor C om een aantal redenen. Één daarvan is dat C een zuivere procedurele taal is. Voor amateurs, zoals de beoogd lezers en ikzelf, is dat echt véél simpeler dan OOP. Python geeft voor mij meer bezwaren, maar dit is een van de belangrijkste.

Vanuit C is de stap naar OOP makkelijker dan direct OOP, naar mijn overtuiging. Dus als C de basis heeft gelegd ga ik door naar C++ of Rust. En dan heb je imho voldoende basis om iedere taal te leren die je maar wil. Desnoods Python :)

Louren van Garderen

Leuk experiment! Maar Python of R zijn een stuk toegankelijker, tegenwoordig zelfs bij de meeste universiteiten verplicht onderdeel van het curriculum.

Is het niet veel makkelijker kloten met Pandas in Python?

Ron Heinen

Als voorbeeld hoe gemakkelijk het is om GPT4 in Bing Chat een computerprogramma te laten genereren heb ik de volgende vraag gesteld in Bing Chat: "Genereer een C programma met als input parameters een textfile en een letter en als output het aantal keren dat deze non-case-sensitive letter in de text voorkomt."

De resultaat kun je vinden op:

https://www.ndax.eu/LJQ7nj+wV4BYFkKx-PuU.c

Zo'n door AI gegenereerd computerprogramma kun je bijvoorbeeld testen met een aantal text files als input waarvoor je weet wat het goede antwoord is.

Reageren op een artikel kan tot drie maanden na plaatsing. Reageren op dit artikel is daarom niet meer mogelijk.

Aanmelden nieuwsbrief

Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.