Chapter 3 Practical example: Big Five Inventory for personality assessment

The BFI is a widely recognized instrument for assessing five key dimensions of personality: Openness, Conscientiousness, Extraversion, Agreeableness, and Neuroticism. For the purposes of this guide, I will focus on implementing the BFI based on the work of Rammstedt and colleagues (2018). This practical example demonstrates how participants can receive a PDF download after responding to BFI items on SoSci Survey.

To implement the BFI in SoSci Survey, create a new questionnaire and add the BFI items as questions. Make sure to name the variables according to the following naming convention, as I will use these variable names in this code:

  • Openness: Offenheit
  • Conscientiousness: Gewissenhaftigkeit
  • Extraversion: Extraversion
  • Agreeableness: Vertraeglichkeit
  • Neuroticism: Neurotizismus

The code assumes that there is a question category BF01 with individual item 1 to item 30, previous to the code implementation.

As item 1,3,7,8,10,14,17,19,20,21,24,26,27,28 and 30 are reversed, we can either set these items as reversed items within Sosci Survey, or calculate the reversed score using the value() function to fetch the respondent’s original score and then use the put() function to save the recalculated score into an internal variable. See the SoSci Survey Guide for detailed instructions for in-php reversing. In the following php code chunck, I calculate means for items that are reversed within sosci survey.

// Wert/Ergebnis ermitteln
// Neurotizsmus
$Neurotizismus= valueMean(array(
'BF01_04', 
'BF01_09', 
'BF01_14', 
'BF01_19', 
'BF01_24', 
'BF01_29' 
));
debug($Neurotizismus);

// Extraversion
$Extraversion= valueMean(array(
'BF01_01', 
'BF01_06', 
'BF01_11', 
'BF01_16', 
'BF01_21', 
'BF01_26'
));
debug($Extraversion);

// Offenheit
$Offenheit= valueMean(array(
'BF01_05', 
'BF01_10', 
'BF01_15', 
'BF01_20', 
'BF01_25', 
'BF01_30' 
));
debug($Offenheit);

// Vertraeglichkeit
$Vertraeglichkeit= valueMean(array(
'BF01_02', 
'BF01_07', 
'BF01_12', 
'BF01_17', 
'BF01_22', 
'BF01_27'  
));
debug($Vertraeglichkeit);

// Gewissenhaftigkeit
$Gewissenhaftigkeit= valueMean(array(
'BF01_03', 
'BF01_08', 
'BF01_13', 
'BF01_18', 
'BF01_23', 
'BF01_28'  
));
debug($Gewissenhaftigkeit);

replace('%Neurotizismus%', sprintf('%1.1f', $Neurotizismus));
replace('%Extraversion%', sprintf('%1.1f', $Extraversion));
replace('%Offenheit%', sprintf('%1.1f', $Offenheit));
replace('%Vertraeglichkeit%', sprintf('%1.1f', $Vertraeglichkeit));
replace('%Gewissenhaftigkeit%', sprintf('%1.1f', $Gewissenhaftigkeit));


$facetten = array('Neurotizismus', 'Extraversion', 'Offenheit', 'Vertraeglichkeit', 'Gewissenhaftigkeit');

A limitation of the initial approach is that it presumes all participants provide valid responses to every item. However, one may wish to compute indices conditionally, for instance, only when all responses are present and valid. This alternative strategy sets an index to 0 if any of the items used to calculate the mean have an invalid response. An example demonstrating this approach is provided below, in which an invalid response is defined as a value less than or equal to 0.

// Neurotizismus
$nitems = array(value('BF01_04'), value('BF01_09'), value('BF01_14'), value('BF01_19'), value('BF01_24'), value('BF01_29'));
$isValid = true;
$sum = 0;
foreach ($nitems as $value) {
    if ($value <= 0) {
        $isValid = false;
        break;
    }
    $sum += $value;
}
if ($isValid) {
    $Neurotizismus = $sum / count($nitems);
} else {
    $Neurotizismus = 0;
}
debug($Neurotizismus);

// Extraversion
$eitems = array(value('BF01_01'), value('BF01_06'), value('BF01_11'), value('BF01_16'), value('BF01_21'), value('BF01_26'));
$isValid = true;
$sum = 0;
foreach ($eitems as $value) {
    if ($value <= 0) {
        $isValid = false;
        break;
    }
    $sum += $value;
}
if ($isValid) {
    $Extraversion = $sum / count($eitems);
} else {
    $Extraversion = 0;
}
debug($Extraversion);

// Offenheit
$oitems = array(value('BF01_05'), value('BF01_10'), value('BF01_15'), value('BF01_20'), value('BF01_25'), value('BF01_30'));
$isValid = true;
$sum = 0;
foreach ($oitems as $value) {
    if ($value <= 0) {
        $isValid = false;
        break;
    }
    $sum += $value;
}
if ($isValid) {
    $Offenheit = $sum / count($oitems);
} else {
    $Offenheit = 0;
}
debug($Offenheit);

// Vertraeglichkeit
$vitems = array(value('BF01_02'), value('BF01_07'), value('BF01_12'), value('BF01_17'), value('BF01_22'), value('BF01_27'));
$isValid = true;
$sum = 0;
foreach ($vitems as $value) {
    if ($value <= 0) {
        $isValid = false;
        break;
    }
    $sum += $value;
}
if ($isValid) {
    $Vertraeglichkeit = $sum / count($vitems);
} else {
    $Vertraeglichkeit = 0;
}
debug($Vertraeglichkeit);

// Gewissenhaftigkeit
$gitems = array(value('BF01_03'), value('BF01_08'), value('BF01_13'), value('BF01_18'), value('BF01_23'), value('BF01_28'));
$isValid = true;
$sum = 0;
foreach ($gitems as $value) {
    if ($value <= 0) {
        $isValid = false;
        break;
    }
    $sum += $value;
}
if ($isValid) {
    $Gewissenhaftigkeit = $sum / count($gitems);
} else {
    $Gewissenhaftigkeit = 0;
}
debug($Gewissenhaftigkeit);


replace('%Neurotizismus%', sprintf('%1.1f', $Neurotizismus));
replace('%Extraversion%', sprintf('%1.1f', $Extraversion));
replace('%Offenheit%', sprintf('%1.1f', $Offenheit));
replace('%Vertraeglichkeit%', sprintf('%1.1f', $Vertraeglichkeit));
replace('%Gewissenhaftigkeit%', sprintf('%1.1f', $Gewissenhaftigkeit));


$facetten = array('Neurotizismus', 'Extraversion', 'Offenheit', 'Vertraeglichkeit', 'Gewissenhaftigkeit');

After implementing a suiting php calculation of indices, I proceed to implement the radar chat. In this example, I create a radar chart featuring two datasets: one containing our previously calculated indices and another with specified norm scores. These norm scores can be obtained from scholarly publications; in this case, I use data from a study by Rammstedt et al. (2018) with N = 1,338.

Subsequent to the PHP-code, I implement the HTML-Code. The HTML-Code is seperated it into three parts for ease of explanation. It is crucial to note that all three parts must be included in a single, uninterrupted HTML block to accurately reproduce the results. The first part of this HTML code serves multiple functions: it facilitates the creation of the actual PDF file, displays a download button beneath the radar chart, and establishes the canvas for the plot. For better visibility, I configure the button to appear in bold and steelblue text.

Part1:

<title>Chart with Download Link</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"></script>


    <style>
        /* Make the button text bold */
        #downloadPdf {
        font-weight: bold;
        color: steelblue;

        }
    </style>
     <button id="downloadPdf" type="button">Download PDF</button> 
 
 <div>
  <canvas id="myChart"></canvas>
 </div>

Part2:

Here, I add the real participant data and the specified norm scores on one single radar chart. Specifically, the second dataset used, is labeled Normwerte to plot [2.74, 3.13, 3.27, 2.70, 2.70] as fixed values. Additonally, the scale is set from 1 to 5 and label sizes are adjusted.

//<!-- This should be below part 1  -->
<script>
  const { jsPDF } = window.jspdf;
  const ctx = document.getElementById('myChart');
  new Chart(ctx, {
    type: 'radar',
    data: {
      labels: ['Neurotizismus', 'Extraversion', 'Offenheit', 'Vertraeglichkeit', 'Gewissenhaftigkeit'],
      datasets: [{
        
//real data
label: 'individuelle Facettenausprägung',
        data: ['%Neurotizismus%', '%Extraversion%', '%Offenheit%', '%Vertraeglichkeit%', '%Gewissenhaftigkeit%'],
    fill: true,
    backgroundColor: [
      'rgba(153, 102, 255, 0.2)'
    ],
    borderColor: [
      'rgba(153, 102, 255, 1)'
    ],
        borderWidth: 1.5

    }, {

//norm data
label: 'Normwerte',
        data: [2.74,3.13,3.27,2.70,2.70],
    fill: true,
    backgroundColor: [
      'rgba(75, 192, 192, 0.2)'
    ],
    borderColor: [
      'rgba(75, 192, 192, 1)'
    ],
        borderWidth: 1.5


//options
      }]
    },
    options: { 
      scales: {
        r: {
          min: 0,
          max: 5,
          pointLabels: {
            font: {
              size: 15
            }
          },
          angleLines: {
            display: false // Hide the lines connecting the center to the labels
          },
          ticks: {
            stepSize: 1, // Set the step size for labels
            callback: function(value, index, values) {
              // Skip labels for specific values (e.g., 0) as 0 is not a real score (1-5)
              if (value === 0) {
                return '';
              }
              return value;
            }
          }
        }
      }
    }
  });

Part3:

In this segment of code, I write the PDF file and make it visually appealing. This involves incorporating various design elements such as headers, footers, lines, and textual content. I recommend including a brief explanation to guide participants in interpreting their results, highlighting the conditions and limitations of these interpretations. It is important to note that text sizes are specifically adjusted for this content. Should one wish to include different or additional blocks of text, further adjustments concerning text size, positioning, and other visual elements may be needed.

  //<!-- This should be below part 2  -->
document.getElementById('downloadPdf').addEventListener('click', function() {
    html2canvas(ctx, {
      onrendered: function(canvas) {
        const imgData = canvas.toDataURL('image/png', 1.0);
        const pdf = new jsPDF('p', 'mm', 'a4');
        const width = pdf.internal.pageSize.getWidth();
        const imgWidth = width - 40;
        const imgHeight = (canvas.height * imgWidth) / canvas.width;

        // Add header
        pdf.setFontSize(16);
        pdf.text("Individuelle Auswertung", 105, 10, { align: 'center' });
        pdf.setDrawColor(70, 130, 180); // Set color to steel blue
        pdf.setLineWidth(0.5);
        pdf.line(20, 12, 190, 12);

        // Add header
        pdf.setFontSize(12);
        pdf.text("Untertitel", width / 2, 20, { align: 'center' });

        // Add text element above the chart
        pdf.setFontSize(10);
        const text = 
"Im Folgenden werden Ihre Persönlichkeitsmessungen anhand der BIG-5 präsentiert. Die BIG-5 Persönlichkeiten sind ein Modell der Persönlichkeitspsychologie, das die fünf Hauptdimensionen der Persönlichkeit beschreibt. Diese Dimensionen werden als Neurotizismus, Extraversion, Offenheit für Erfahrungen, Verträglichkeit und Gewissenhaftigkeit bezeichnet. Zusammengenommen bilden diese fünf Dimensionen ein umfassendes Bild der Persönlichkeit einer Person und können helfen, Ihr Verhalten und Ihre Interaktionen mit anderen besser zu verstehen. Es ist wichtig zu beachten, dass die BIG-5 Persönlichkeiten keine festen Kategorien sind und dass jeder Mensch einzigartig ist und seine eigenen individuellen Eigenschaften und Charakterzüge hat. Eine Beschreibung zu den einzelnen Facetten findet sich am Ende der Seite. Vergleichsdaten liefert die Arbeit von Rammstedt und Kollegen (2018), welche die Persönlichkeitsausprägungen von 1.338 Personen überprüft haben.";
        const lines = pdf.splitTextToSize(text, 180);
        const x = (width - 180) / 2; // Center the text block
        pdf.text(lines, x, 35); // Start the text at position (x, 35)

        // Calculate the position of the image based on the length of the text
        const imagePosition = 35 + (lines.length * 5);



       // Add the image
        pdf.addImage(imgData, 'PNG', (width - imgWidth * 0.9) / 2, imagePosition, imgWidth * 0.9, imgHeight * 0.72, 'NONE', 'FAST', 0, -imgHeight * 0.2);


        // Add construct definitions below the chart
        pdf.setFontSize(9);
        const textBelow = `
**Neurotizismus: Diese Dimension beschreibt die Tendenz, emotional instabil und anfällig für Stress zu sein. Menschen mit hohem Neurotizismus sind empfindlich, ängstlich und unruhig. Sie neigen dazu, sich Sorgen zu machen und haben ein hohes Bedürfnis nach Sicherheit.

**Extraversion: Diese Dimension beschreibt die Tendenz, aktiv und offen im sozialen Umgang zu sein. Menschen mit hoher Extraversion sind gesellig, energiegeladen und kontaktfreudig. Sie suchen die Gesellschaft anderer Menschen und genießen es, neue Leute kennenzulernen. Sie sind auch selbstbewusst und können ihre Meinungen offen äußern.

**Offenheit für Erfahrungen: Diese Dimension bezieht sich auf die Bereitschaft, neue Ideen und Erfahrungen zu akzeptieren und zu suchen. Menschen mit hoher Offenheit sind neugierig, kreativ und abenteuerlustig. Sie sind offen für neue Erfahrungen und haben eine große Bandbreite an Interessen. Sie sind auch offen für komplexe Ideen und können flexibel denken.

**Verträglichkeit: Diese Dimension bezieht sich auf die Fähigkeit, empathisch und kooperativ im sozialen Umgang zu sein. Menschen mit hoher Verträglichkeit sind freundlich, zuvorkommend und hilfsbereit. Sie sind auch geduldig und verstehen die Perspektiven anderer Menschen. Sie haben auch ein geringes Bedürfnis, andere zu kontrollieren oder zu manipulieren.

**Gewissenhaftigkeit: Diese Dimension bezieht sich auf die Fähigkeit, sorgfältig und verantwortungsbewusst zu handeln. Menschen mit hoher Gewissenhaftigkeit sind organisiert, zuverlässig und diszipliniert. Sie planen ihre Zeit und ihre Aktivitäten sorgfältig und setzen sich Ziele, die sie erreichen wollen. Sie sind auch selbstkontrolliert und können ihre Impulse unter Kontrolle halten.

Nähere Informationen in "The Five-Factor Model of Personality: Theoretical Perspectives" von Paul T. Costa Jr. und Robert R. McCrae (1996), in der Zeitschrift Annual Review of Psychology.`;

   const linesBelow = pdf.splitTextToSize(textBelow, 180);
   pdf.text(linesBelow, x, imagePosition + imgHeight - 57);  // Position below the image


    pdf.setDrawColor(70, 130, 180);  // Set color to steel blue
    pdf.line(20, 285, 190, 285);  // Draw line
    pdf.setFontSize(6);  // Set font size


    // Your footer text
    const footerText = 
`Dieses Dokument wurde automatisiert erstellt und entspricht den Datenschutzbestimmungen der DSGVO. Weder das Herunterladen des PDFs noch die gemachten Angaben können auf Ihre Person zurückgeführt werden. Es ist nicht möglich, dieses Dokument nachträglich anzufragen, da es nur während der Teilnahme an der Studie erstellt werden kann und auch nur von der befragten Person einsehbar ist.`;

    // Split text to fit within page margins
    const splitFooter = pdf.splitTextToSize(footerText, 140);  // 140 here means the text will wrap after reaching 140 units width

    // Output the lines
    pdf.text(splitFooter, pdf.internal.pageSize.getWidth() / 2, 287, { align: 'center', maxWidth: 140 });

    // Output date and time
    pdf.text(new Date().toLocaleString('de-DE'), pdf.internal.pageSize.getWidth() - 40, 10);

        // Save the PDF with the custom filename
        pdf.save("Ihre Auswertungsergebnisse.pdf");

      }
    });
  });
</script>