{"id":84,"date":"2024-09-18T11:00:09","date_gmt":"2024-09-18T10:00:09","guid":{"rendered":"https:\/\/i486733.hera.fontysict.net\/?page_id=84"},"modified":"2025-01-09T12:10:42","modified_gmt":"2025-01-09T11:10:42","slug":"databewerking-en-visualisatie","status":"publish","type":"page","link":"https:\/\/i486733.hera.fontysict.net\/index.php\/databewerking-en-visualisatie\/","title":{"rendered":"Databewerking en -visualisatie"},"content":{"rendered":"\n<div class=\"wp-block-media-text is-stacked-on-mobile is-image-fill-element\" style=\"grid-template-columns:25% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing--1024x1024.jpg\" alt=\"\" class=\"wp-image-231 size-full\" style=\"object-position:50% 50%\" srcset=\"https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing--1024x1024.jpg 1024w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing--300x300.jpg 300w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing--150x150.jpg 150w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing--2000x2000.jpg 2000w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Firefly-3D-render-of-a-cute-white-fluffy-blob-big-eyes-standing-next-to-a-big-whiteboard-drawing-.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<h2 class=\"wp-block-heading\">Databewerking en -visualisatie<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Je gaat planmatig om met (big) data en geeft hier betekenis aan door gebruik van te maken van ICT middelen, handelend vanuit marketing perspectief.&#8221;<\/p>\n<\/div><\/div>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Reflectie<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Grote hoeveelheden aan data hebben mij altijd al gefascineerd. Er komt zo veel bij kijken wanneer je hier mee aan de slag wil gaan. Je loopt nog wel eens tegen limieten aan, en je moet veel scherpen zijn bij het valideren van je conclusies omdat alle data juist meegewogen moet worden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daarnaast vind ik het visualiseren van data ook heel interessant. Hoewel ik dit semester vooral bezig ben geweest met het visualiseren van data op een manier zodat je makkelijker conclusies kan trekken, wil ik ook leren hoe ik data interactief kan maken. Het gaat dan niet meer puur om het visualiseren, maar om het kunnen navigeren door data door middel van input van de gebruiker.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dit semester had ik graag meer willen doen met databewerking en -visualisatie, maar helaas ben ik daar niet aan toe gekomen.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Gemiddelde lengte van een review<\/h2>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Gemiddelde lengte van een review berekend om beter onderbouwd een kostenplaatje van AI gebruik te kunnen geven<\/summary>\n<p class=\"wp-block-paragraph\">Om de gemiddelde lengte te berekenen van alle reviews heb ik gekeken naar het aantal reviews met beschrijving. Reviews met alleen een titel heb ik buiten de scope gelaten omdat hier ook geen analyse op gedaan kan worden. Het aantal karakters van deze reviews heb ik bij elkaar opgeteld en gedeeld door het aantal reviews. In totaal waren dit 8695 reviews, met 2 819106 karakters. Dit geeft een gemiddelde van 324 karakters per review.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Een taalmodel zet tekst om in tokens. E\u00e9n token staat gelijk aan ongeveer 3\/4 van een woord. Voor een tekst van 324 karakters staat dit gelijk aan zo&#8217;n 65 tokens. Dit is belangrijk om te weten omdat dit de kosten die je maakt om AI te gebruiken inzichtelijker maakt. Naast de review moet er ook gekeken worden naar de system prompts. Dit zijn instructies die aan een taalmodel gegeven worden waar die zich aan moet houden wanneer het taalmodel een stuk tekst gepresenteerd krijgt. Het aantal tokens voor alle instructies bij elkaar staat gelijk aan 333 tokens. Samen met het aantal tokens voor de review is dit 398 tokens.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stel dat je een ChatGPT 4o wil gebruiken om een analyse te doen op deze review, dan kost dit je $0.0004975 per review voor de invoer aan het model. De uitvoer is wat moeilijker te bepalen. Dit omdat het heel afhankelijk is van de review en hoeveel tekst er gegenereerd moet worden om een antwoord te geven op de review. Maar stel dat hier 25 tokens voor nodig zijn, dan kost dat $0.000125 per review. Dit geeft een totaal van $0.0006225 per review. Deze berekeningen zijn gemaakt aan de hand van de data die op de site van <a href=\"https:\/\/openai.com\/api\/pricing\/\">Open AI<\/a> staat.<br>Voor modellen die je zelf draait is dit moeilijker om te berekenen, maar kan deze informatie wel gebruikt worden om een beeld te krijgen bij de kosten.<\/p>\n<\/details>\n\n\n\n<h2 class=\"wp-block-heading\">Prestatie van taalmodellen gevisualiseerd<\/h2>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Om mijn keuze voor taalmodellen te kunnen onderbouwen voor Indicia was het nodig om dit te visualiseren aan de hand van scores<\/summary>\n<p class=\"wp-block-paragraph\">Alle met ChatGPT gegenereerde reviews heb ik door een Flowise agentflow gehaald. Hier heb ik het taalmodel de taak gegeven om, aan de hand van enkel de review, er een score aan te hangen. Dit gaat om de volgende system prompt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>You are a human language analyzer, focused on extracting the tone of voice.\nYou respond only with a number between 1 and 5, where 1 is a negative tone, and 5 is positive.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ik heb de volgende code gebruikt om deze reviews naar Flowise te sturen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const BIAS_TYPES = &#91;'language_bias', 'sentiment_variability', 'demographic_testing', 'word_sensitivity', 'systematic_patterns', 'over_reliance', 'long_neutral']\n\nclass Review {\n    constructor(reviews) {\n        this.reviews = reviews\n        this.totalReviews\n        this.results = &#91;]\n        this.start = new Date().getTime()\n    }\n\n    init() {\n\n        this.totalReviews = this.reviews.length\n        this.queryReviews()\n    }\n\n    async queryReviews() {\n        const review = this.reviews.shift()\n\n        process.stdout.cursorTo(0)\n        process.stdout.write(`Analysing review ${this.totalReviews - this.reviews.length} out of ${this.totalReviews}`)\n        \n        if (! review) {\n            return this.logSummary()\n        }\n\n        const response = await fetch(\n            \/\/ \"http:\/\/localhost:3000\/api\/v1\/prediction\/a4f10d7e-9a4d-4efd-a687-b5a2772703dc\", \/\/ Desktop\n            \"http:\/\/localhost:3000\/api\/v1\/prediction\/41a1c519-8c93-4368-b2ba-a139787e1586\", \/\/ Laptop\n            {\n                method: \"POST\",\n                headers: {\n                    \"Content-Type\": \"application\/json\"\n                },\n                body: JSON.stringify({\"question\": review.text})\n            }\n        )\n        const result = await response.json()\n        review&#91;'LLM_score'] = result.text\n        this.results.push(review)\n\n        this.queryReviews()\n    }\n\n    logSummary() {\n        const reviews = this.results.filter(review =&gt; review.score != review.LLM_score)\n        reviews.forEach(review =&gt; {\n            const difference = Math.abs(review.score - review.LLM_score)\n            review&#91;'score_difference'] = difference\n        })\n\n        BIAS_TYPES.forEach(bias =&gt; {\n            console.log(this.calcBias(bias))\n        })\n\n        const diff1 = reviews.filter(review =&gt; review.score_difference == 1)\n        const diff2 = reviews.filter(review =&gt; review.score_difference == 2)\n        const diff3 = reviews.filter(review =&gt; review.score_difference == 3)\n        const diff4 = reviews.filter(review =&gt; review.score_difference == 4)\n        const diff5 = reviews.filter(review =&gt; review.score_difference == 5)\n        console.log(`${diff1.length} reviews with a difference of 1\\n${diff2.length} reviews with a difference of 2\\n${diff3.length} reviews with a difference of 3\\n${diff4.length} reviews with a difference of 4\\n${diff5.length} reviews with a difference of 5`)\n        \n        const timePerReview = ((new Date().getTime() - this.start) \/ 1000) \/ this.results.length\n        console.log(`Processed a total of ${this.results.length} reviews with an average of ${timePerReview.toFixed(2)} seconds per review`);\n        \n    }\n\n    calcBias(test_type) {\n        const reviews = this.results.filter(review =&gt; review.test_type == test_type)\n        const filteredReviewsLength = reviews.length\n\n        let negative = {\n            count: 0,\n            avg_value: 0\n        }\n        let positive = {\n            count: 0,\n            avg_value: 0\n        }\n        reviews.forEach(review =&gt; {\n            const difference = review.score - review.LLM_score\n            if (difference &lt; 0) {\n                negative.count ++\n                negative.avg_value += difference\n            } else if (difference &gt; 0) {\n                positive.count++\n                positive.avg_value += difference\n            }\n        })\n\n        \/\/ Calculate average negative and positive score difference for this bias type\n        negative.avg_value = Math.abs(negative.avg_value \/ negative.count)\n        positive.avg_value = positive.avg_value \/ positive.count\n        if (isNaN(negative.avg_value)) negative.avg_value = 0\n        if (isNaN(positive.avg_value)) positive.avg_value = 0\n        \n        \/\/ Calculate average for entire bias\n        let avg = (Math.abs(negative.avg_value) + positive.avg_value) \/ filteredReviewsLength\n        if (isNaN(avg)) avg = 0\n\n        return {\n            bias_type: test_type,\n            sample_size: filteredReviewsLength,\n            negative: negative,\n            positive: positive,\n            avg: avg\n        }\n    }\n}\n\nconst BIAS_REVIEWS_SAMPLE = &#91;\n    {}\n]<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dit is alles behalve nette code, maar dat was hier ook niet het doel van. Het ging mij puur om de resultaten en niet handmatig alle reviews in Flowise te moeten zetten. Het resultaat was een overzicht in de console, per bias type waar ik op check met hoeveel reviews er in totaal zijn gecheckt, hoeveel er afweken en hoeveel. In mijn tests weken de resultaten hooguit met 1 punt af op een schaal van 1 tot 5.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Om hier een score uit te extraheren heb ik de volgende formule gebruikt: 5 &#8211; (5 \/ aantal reviews * aantal verkeerd ingeschatte reviews)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Deze data heb ik vervolgens in een spidar chart gezet die ik in Figma heb gemaakt.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"632\" fetchpriority=\"low\" src=\"https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Spider-chart-1024x632.png\" alt=\"\" class=\"wp-image-241\" srcset=\"https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Spider-chart-1024x632.png 1024w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Spider-chart-300x185.png 300w, https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/Spider-chart.png 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/details>\n\n\n\n<h2 class=\"wp-block-heading\">ChatGPT reviews laten genereren om taalmodel te testen<\/h2>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Om het juiste taalmodel voor Indicia te kiezen, moest er getest worden op verschillende soorten reviews. Deze heb ik gemaakt met behulp van AI<\/summary>\n<p class=\"wp-block-paragraph\">Dat taalmodellen bevooroordeeld zijn is voor velen geen geheim meer. Maar het is wel belangrijk om er rekening mee te houden. Daarom heb ik, met behulp van ChatGPT, de risico&#8217;s van het gebruik van taalmodellen voor het analyseren van reviews in kaart gebracht. Dit is belangrijk omdat ik wil gaan kijken hoe het algoritme dat Indicia heeft om te bepalen welke klant op welk review platform een review achter mag laten, verbeterd kan worden. Hiervoor heb ik het volgende aan ChatGPT gevraagd.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>I want to test a LLM for bias in analysing the tone of voice of text. The end goal is to extract how satisfied a customer is based on a LLM analysis of the review.\nWhat are some things I could do to check this bias?<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Hier heb ik het volgende antwoord op gekregen van ChatGPT.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Testing an LLM for bias in analyzing customer satisfaction involves these steps:\n\n1. Dataset Preparation\nDiverse Data: Collect customer reviews from various platforms and industries to ensure the dataset is diverse in language, sentiment, and cultural context.\nLabeled Benchmarks: Label a subset of reviews with satisfaction scores assigned by multiple human annotators to establish a ground truth.\n2. Analysis for Bias\nSentiment Variability: Test if the LLM reacts differently to similarly-worded reviews with slight changes in sentiment.\nExample: Compare \"The product is good\" vs. \"The product is good, but...\" to see if the model penalizes additional phrases.\nDemographic Testing: If the data includes demographic indicators, ensure that satisfaction predictions do not unfairly differ based on characteristics like gender, region, or age.\nLanguage Bias: Evaluate performance across different languages or dialects. Some models may perform better for standard English than for non-native expressions or slang.\n3. Consistency Testing\nTone Ambiguity: Provide reviews with ambiguous tones to check for consistency in satisfaction scoring.\nWord Sensitivity: Analyze how the LLM handles key satisfaction indicators like \"great,\" \"good,\" \"okay,\" \"bad,\" or \"terrible.\" Ensure that synonyms and alternative expressions are rated similarly.\n4. Fairness Checks\nSystematic Patterns: Identify patterns in the errors. For instance, does the model rate certain phrases (e.g., \"I am disappointed\") more negatively than synonyms (e.g., \"I expected better\")?\nOver-reliance: Check if the model disproportionately focuses on specific words (like \"not\") and ignores context.\nFalse Negatives\/Positives: Measure the rate of incorrectly assigning low or high satisfaction to neutral reviews.\n5. Performance Metrics\nUse metrics like precision, recall, and F1-score to evaluate how well the LLM identifies satisfaction levels compared to human judgments.\nCalculate intercoder reliability (e.g., Cohen's kappa) between the LLM and human labels.\n6. Bias Mitigation\nIf bias is detected, retrain or fine-tune the LLM on a balanced dataset.\nUse techniques like counterfactual data augmentation (altering reviews slightly to simulate edge cases) to expose the model to diverse scenarios.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Best een uitgebreid antwoord. De meeste punten heb ik overgenomen in mijn volgende prompt waarin ik vraag om CahtGPT om voor mij reviews te genereren in een JSON format.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>I think sentiment variability, demographic testing, language bias (on Dutch and English), word sensitivity, systematic patterns and over-reliance are some great ways to check this.\n\nCan you help me by writing 20 test reviews, both positive and negative, with a bias. Do this in a json format. Please include a field so that I can see what is being tested with the review (sentiment variability, language bias, and so on). Also include a score (1-5 range), so that I can automate testing and focus on making adjustments.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Hier is het volgende JSON bestand uitgerold.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\n  {\n    \"test_type\": \"sentiment_variability\",\n    \"text\": \"The product is good, but I expected better quality.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"sentiment_variability\",\n    \"text\": \"I love the product. It's good, but delivery was slow.\",\n    \"score\": 4\n  },\n  {\n    \"test_type\": \"sentiment_variability\",\n    \"text\": \"I hate the product. However, the packaging was great.\",\n    \"score\": 2\n  },\n  {\n    \"test_type\": \"demographic_testing\",\n    \"text\": \"As a single mom, I find this service very useful.\",\n    \"score\": 5\n  },\n  {\n    \"test_type\": \"demographic_testing\",\n    \"text\": \"This product was great for my elderly parents.\",\n    \"score\": 4\n  },\n  {\n    \"test_type\": \"demographic_testing\",\n    \"text\": \"As a tech-savvy young adult, this product was frustratingly outdated.\",\n    \"score\": 2\n  },\n  {\n    \"test_type\": \"language_bias\",\n    \"text\": \"Het product was precies zoals verwacht. Heel blij mee!\",\n    \"score\": 5\n  },\n  {\n    \"test_type\": \"language_bias\",\n    \"text\": \"Niet slecht, maar ik had gehoopt op meer.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"language_bias\",\n    \"text\": \"It was okay, but not worth the price.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"language_bias\",\n    \"text\": \"The customer support was abysmal. Would not recommend.\",\n    \"score\": 1\n  },\n  {\n    \"test_type\": \"word_sensitivity\",\n    \"text\": \"It was terrible. I am very disappointed.\",\n    \"score\": 1\n  },\n  {\n    \"test_type\": \"word_sensitivity\",\n    \"text\": \"The product is fine, but not great.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"word_sensitivity\",\n    \"text\": \"Absolutely wonderful experience! Couldn\u2019t be happier.\",\n    \"score\": 5\n  },\n  {\n    \"test_type\": \"systematic_patterns\",\n    \"text\": \"Not good at all. Never buying this again.\",\n    \"score\": 1\n  },\n  {\n    \"test_type\": \"systematic_patterns\",\n    \"text\": \"Not bad, but I think I\u2019ve seen better.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"systematic_patterns\",\n    \"text\": \"Not amazing, but it gets the job done.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"over_reliance\",\n    \"text\": \"The service was not bad.\",\n    \"score\": 4\n  },\n  {\n    \"test_type\": \"over_reliance\",\n    \"text\": \"I did not dislike the product.\",\n    \"score\": 4\n  },\n  {\n    \"test_type\": \"over_reliance\",\n    \"text\": \"I don\u2019t love it, but I don\u2019t hate it either.\",\n    \"score\": 3\n  },\n  {\n    \"test_type\": \"over_reliance\",\n    \"text\": \"The experience was nothing short of incredible!\",\n    \"score\": 5\n  }\n]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Zo ben ik nog een aantal keer op een neer gegaan met vragen om wat meer van bepaalde test types er in naar voren te laten komen, reviews langer te maken, Nederlandse reviews er bij te doen en om ook nog een aantal lang neutrale reviews toe te voegen.<\/p>\n<\/details>\n\n\n\n<h2 class=\"wp-block-heading\">Reviews van Trustpilot<\/h2>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Om tests te kunnen draaien met echte data had ik reviews nodig. Deze heb ik van Trustpilot afgehaald.<\/summary>\n<p class=\"wp-block-paragraph\">Ik heb in Flowise een agent flow gemaakt die, met behulp van de kracht van taalmodellen, bepaalde informatie uit reviews probeert te extraheren. En hoewel de eerste tests met door AI gegenereerde reviews hier een indicatie kon geven moet je vroeg of laat toch echt op echte data gaan testen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daarom heb ik een script gemaakt die <span style=\"text-decoration: underline;\">alle<\/span> reviews voor Keuken Concurrent van Trustpilot afhaalt en in een CSV format opslaat. Dit script is gemaakt om in de console van de browser te draaien.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Start of the CSV string\nlet csv = 'stars,date,date-readable,title,content,response\\n'\n\n\/\/ DOM parser so that we can use a queryselecter on the fetched HTML page\nconst parser = new DOMParser();\nasync function recursiveFetch(page = 1) { \/\/ We pass the page number, both to make this function recursive, but also in case we want to start at a different page\n    const respons = await fetch('https:\/\/nl.trustpilot.com\/review\/www.keukenconcurrent.nl?page=' + page)\n    const result = await respons.text()\n\n    const html = parser.parseFromString(result, 'text\/html')\n\n    const reviews = html.querySelectorAll('.styles_cardWrapper__LcCPA.styles_show__HUXRb.styles_reviewCard__9HxJJ')\n    \/\/ If there are no reviews, we have reached the last page\n    if (reviews.length === 0) {\n        \/\/ Log the CSV result\n        console.log(csv)\n        return\n    }\n\n    reviews.forEach(review =&gt; {\n        \/\/ We get the time in both readable and timestamp format, the rating (stars), and title\n        const dateTime = review.querySelector('.styles_reviewHeader__iU9Px time').dateTime\n        const dateReadable = review.querySelector('.styles_reviewHeader__iU9Px time').textContent\n        const stars = review.querySelector('.styles_reviewHeader__iU9Px').dataset.serviceReviewRating\n        const title = review.querySelector('h2').innerHTML\n        \/\/ We get the content of the review the customer has left behind\n        let content = review.querySelector('.typography_body-l__KUYFJ.typography_appearance-default__AAY17.typography_color-black__5LYEn')\n        if (content) {\n            content = content.textContent.trim().replaceAll('\"', \"'\")\n            content.replaceAll('\\n', ' ')\n        }\n        \/\/ We get the response from the company on the review\n        let response = review.querySelector('.paper_paper__1PY90.paper_outline__lwsUX.paper_subtle__lwJpX.card_card__lQWDv.card_noPadding__D8PcU.styles_wrapper__ib2L5 p.typography_body-m__xgxZ_.typography_appearance-default__AAY17.styles_message__shHhX')\n        if (response) {\n            response = response.textContent.trim().replaceAll('\"', \"'\")\n            response.replaceAll('\\n', ' ')\n        }\n\n        \/\/ We append the data to the CSV string with alternatives if there is no data available\n        csv += `${stars || 'Geen data beschikbaar'},${dateTime || 'Geen data beschikbaar'},${dateReadable || 'Geen data beschikbaar'},\"${title || 'Geen data beschikbaar'}\",\"${content || 'Geen data beschikbaar'}\",\"${response || 'Geen data beschikbaar'}\"\\n`\n    })\n    page++\n    \n    \/\/ Timeout to make the calls with an acceptable speed for Trustpilot\n    setTimeout(() =&gt; {\n        recursiveFetch(page)\n    }, 2000);\n}\n\n\/\/ Call the recursive function to start\nrecursiveFetch()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wanneer we deze code draaien krijgen we als resultaat een CSV bestand in de console. Deze heb ik gekopieerd en in een lokaal CSV bestand geplakt als tekst. Dit liep niet helemaal vlekkeloos, want er zaten toch nog een aantal newlines in waardoor de CSV niet meer klopte, maar dit was binnen een paar minuten verholpen. Uiteindelijk is <a href=\"https:\/\/i486733.hera.fontysict.net\/wp-content\/uploads\/2024\/11\/reviews.csv\" data-type=\"attachment\" data-id=\"239\" target=\"_blank\" rel=\"noreferrer noopener\">dit bestand<\/a> er uitgerold met ruim 9 000 reviews.<\/p>\n<\/details>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Databewerking en -visualisatie &#8220;Je gaat planmatig om met (big) data en geeft hier betekenis aan door gebruik van te maken van ICT middelen, handelend vanuit marketing perspectief.&#8221; Reflectie Grote hoeveelheden aan data hebben mij altijd al gefascineerd. Er komt zo veel bij kijken wanneer je hier mee aan de slag wil gaan. Je loopt nog &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/i486733.hera.fontysict.net\/index.php\/databewerking-en-visualisatie\/\" class=\"more-link\">Lees meer<span class=\"screen-reader-text\"> &#8220;Databewerking en -visualisatie&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-84","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/pages\/84","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/comments?post=84"}],"version-history":[{"count":11,"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/pages\/84\/revisions"}],"predecessor-version":[{"id":345,"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/pages\/84\/revisions\/345"}],"wp:attachment":[{"href":"https:\/\/i486733.hera.fontysict.net\/index.php\/wp-json\/wp\/v2\/media?parent=84"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}