Welcome to the LimeSurvey Community Forum

Ask the community, share ideas, and connect with other LimeSurvey users!

Randomisierte Reihenfolge einer MaxDiff-Frage speichern

More
2 days 2 hours ago #274218 by Surveylab_KN
Bitte helfen Sie uns, Ihnen zu helfen und füllen Sie folgende Felder aus:
Ihre LimeSurvey-Version: 6.17.0
Eigener Server oder LimeSurvey-Cloud: Limesurvey-Cloud
Genutzte Designvorlage: Eigenes Template
==================
Hallo zusammen,
ich bin gerade dabei, eine MaxDiff-Frage zu erstellen und war hier mit Hilfe des Forums auch schon relativ erfolgreich. Ich habe fünf verschiedene Blöcke (A-E) mit jeweils vier Items. Pro Block wird über vorab gezogene Zufallszahlen ein Item ausgewählt und in der MaxDiff Frage angezeigt. Mit Hilfe des Workarounds dazu im Handbuch  hat das auch super funktioniert. Ich habe dazu eine Array-by-Column-Frage erstellt und diese mit den Anpassungen im Design-Template auch zum Funktionieren bekommen.

Um Reihenfolge-Effekte auszuschließen, werden Blöcke in der Reihenfolge randomisiert. Dies mache ich über die Funktion "Randomization group name". Auch das funktioniert wunderbar. 

Allerdings sollen nun in einer Folgefrage die gezogenen Items jeweils einzeln noch auf einer 5er Skala abgefragt werden. Dafür sollten die Items aber in der gleichen Reihenfolge wie in der MaxDiff-Frage angezeigt werden. Bei diesem Schritt scheitere ich allerdings. Ich würde in einem ersten Schritt gerne zuerst die angezeigte Reihenfolge im Datensatz speichern. Zuerst wollte ich dies über die Funktion "Qcode.qseq" machen, aber dies speichert mir die Reihenfolge der Subquestions, ich benötige allerdings die Reihenfolge der Antworten. 

Wenn jemand hierfür eine Lösung kennt, wäre ich dankbar.

Ich habe auch mal eine kurze Beispielbefragung mit meinem bisherigen Setup gemacht. Auf der zweiten Frageseite habe ich es über den Fragetyp Array by column versucht (benötigt keine Anpassungen am Design Template), aber auch hier scheitere ich.

File Attachment:

File Name: MaxDiff_Re...5733.lss
File Size:66.53 KB


Viele Grüße 

Please Log in to join the conversation.

More
2 days 1 hour ago - 2 days 1 hour ago #274221 by Joffm
Hallo,
dies alles erscheint mir im Moment noch sehr konfus.
So wie es jetzt aussieht, erchließe ich, dass Du in der MaxDiff-Frage fünf Items anzeigen willst, wobei jedes aber 4 Ausprägungen haben kann.
Das sind also 1024 verschiedene Möglichkeiten.

Aber jetzt:

Um Reihenfolge-Effekte auszuschließen, werden Blöcke in der Reihenfolge randomisiert. Dies mache ich über die Funktion "Randomization group name". Auch das funktioniert wunderbar. 

Es nützt allerdings überhaupt nichts, wenn sich nur eine einzige Frage in der Randomisierungsgruppe befindet.
Oder was soll dies bedeuten?

Dass die Items A,B,C,... in unterschiedlicher Reihenfolge angezeigt werden, geschieht ja im script (das Du übrigens auch in meinem "Tutorial Matrizen, Kap. 11 findest) in den Zeilen
Code:
    // Call the maxDiff() function
    // Set the second parameter to true for randomized rows
    maxDiff({QID}, true);

"qseq" heißt ja "question sequence"; daher kommt genau das Erwartete raus.

{list(maxDiff2q1_SQ001.qseq,maxDiff2q1_SQ002.qseq)}
 

Die Frage "maxDiff2q1" hat die Nummer 5 (qseq und gseq beginnen ja bei 0)

Auf der zweiten Frageseite habe ich es über den Fragetyp Array by column versucht

Hast Du doch bei der ersten MaxDiff-Frage auch.

Jetzt kommt meine Frage: Was willst Du eigentlich wissen?
Sollen in der Frage maxDiff2q2 die Items einfach in derselben Reihenfolge angezeigt werden wie in q1?
Dazu solltest Du einfach das im script in "shuffleArray" erzeugte array speichern, und dann mittels eines weiteren schriptes in der Matrix-Frage diese Reihenfolge wiederherstellen.
Dies findest Du im "Tutorial 2: Mehrfachennungen,...". Kap. 1.5.2."

Oder Du kannst auch im Voraus ein solches Zufallsreihenfolge-Array erezugen, welches Du dann in beiden Fragen "verwurstest"

Ich habe im Moment keine Zeit ein kleines Beispiel zu machen.
Versuche es selbst einmal.

Bis dann
Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 2 days 1 hour ago by Joffm.

Please Log in to join the conversation.

More
2 days 11 minutes ago - 2 days 11 minutes ago #274223 by Surveylab_KN
Hallo Joffm,

danke für dein schnelles Feedback.

Es tut mir leid, dass meine Beschreibung konfus war. Hatte versucht den Aufbau gut zu erklären, aber der Aufbau ist etwas komplexer. Ich habe fünf Themenbereiche, und aus jedem soll jeweils eines der vier möglichen Items angezeigt werden. Die Auswahl der Items innerhalb der Themenblöcke ist unabhängig voneinander. Eigentlich habe ich eine MaxDiff Frage mit 5 Items die angezeit werden sollen. Allerdings randomisiert.

Genau ich möchte nur die Reihenfolge speichern für die Analyse später und um die Reihenfolge in der nächsten Frage gleich zu machen.

Danke für den Hinweis auf dein Tutorial und das ich einfach die erstellte Array speichern muss. Ich versuche mich mal daran.

Vielen Dank dir schon mal!
 
Last edit: 2 days 11 minutes ago by Surveylab_KN.

Please Log in to join the conversation.

More
1 day 22 hours ago #274225 by Joffm
Jetzt habe ich noch eine Verständnisfrage (interessiert mich einfach):
Warum das Ganze?
Gut, ich kann mir Folgendes vorstellen:
In einem MaxDiff hat man ja nur die Information "Bester- Schlechtester". Aber Du weißt nicht, ob es den Fall gibt "Unter den Blinden ist der Einäugige König". Soll heißen, es kann sein, dass der Teilnehmer alle Items ziemlich mies findet, aber schließlich eines zum Sieger küren muss.
Dann kann die folgende Matrix natürlich Aufschluss geben, welche Abstände in Wirklichkeit vorhanden sind.

Das bringt mich zu dem Schluss: Warum nicht umgekehrt?
Zunächst die Matrix. Wenn es genau einen Max- und einen Minwert gibt, hast Du bereits Deine MaxDiff-Werte und kannst die nächste(n) Fragen überspringen
Wenn es mehrere gibt, dann kannst Du speziell diese Fälle genauer untersuchen, indem Du nur diese anzeigst und nach dem Sieger oder im anderen Fall nach dem absoluten Loser fragst.
Wäre deutlich einfacher zu realisieren.

Dabei ist mir der Header der Matrix "Rating" auch nicht so klar. Wenn es so etwas wie Ränge sein sollen, validiere einfach mit "unique" oder nimm gleich eine Rangreihe.

Joffm

 

Volunteers are not paid.
Not because they are worthless, but because they are priceless

Please Log in to join the conversation.

More
1 day 7 hours ago #274226 by Surveylab_KN
Lieber Joffm,

zuerst du deiner Rückfrage. Mit der zweiten Matrix-Frage, bei der alle Items eingeschätzt werden sollen, ist tatsächlich der Plan hier ein genaueres Bild aller Items zu bekommen. Das ganze Modul ist zu Diskriminierungswahrnehmungen, ich habe es für das Beispiel hier im Forum versucht etwas einfacher zu gestalten. Es ist auch ein kleines Methodenexperiment zu MaxDiff-Fragen in diesem Kontext, deshalb die zweite zusätzliche Frage.

Dank deines Hinweises und deiner super Tutorials (die mir schon oft weitergeholfen haben!) bin ich schon einen guten Schritt weiter, allerdings stoße ich immer noch auf Probleme.

Ich habe nun nach der MaxDiff-Frage eine short text Frage (´maxDiff2order´) eingebaut und folgendes Script in der MaxDiff-Frage eingebaut:
Code:
<script type="text/javascript" charset="utf-8">
function maxDiff(qID, randomize) {
  var thisQuestion = $('#question' + qID);
  var thisTable = $('table.subquestion-list:eq(0)', thisQuestion);
  var thisTbody = $('tbody', thisTable);
 
  // Short-Text-Frage direkt nach der MaxDiff-Frage
  var hiddenQuestion = $(thisQuestion).nextAll('.text-short:eq(0)');
  var hiddenInput = $('input:text', hiddenQuestion);
 
  $(thisQuestion).addClass('max-diff-array');
 
  // Move the columns
  $('thead tr:eq(0)', thisTable).prepend($('thead tr:eq(0) th:eq(1)', thisTable));
  $('tr.answers-list', thisTable).each(function(i) {
    $('td.answer-item:eq(0)', this).prependTo(this);
  });
 
  // Jeder Zeile Code + Index geben
  $('tr.answers-list', thisTable).each(function(i) {
    $(this).attr('data-index', i);
 
    // Bei Array-by-column ist value meist der stabile Teilfragecode
    var code = $('input[type="radio"]', this).first().val();
    $(this).attr('data-code', code);
  });
 
  function saveOrder() {
    var orderArr = [];
    $('tr.answers-list', thisTable).each(function() {
      orderArr.push($(this).attr('data-code'));
    });
    hiddenInput.val(orderArr.join('|')).trigger('change');
  }
 
  function applySavedOrder(savedOrder) {
    var orderArr = savedOrder.split('|');
 
    $(orderArr).each(function(i, code) {
      var row = $('tr.answers-list[data-code="' + code + '"]', thisTable);
      if (row.length) {
        thisTbody.append(row);
      }
    });
  }
 
  // Random rows oder gespeicherte Reihenfolge anwenden
  var savedOrder = $.trim(hiddenInput.val());
 
  if (savedOrder) {
    applySavedOrder(savedOrder);
  } else if (randomize) {
    var rowsArr = [];
    $('tr.answers-list', thisTable).each(function(i) {
      rowsArr.push(i);
    });
 
    shuffleArray(rowsArr);
 
    $(rowsArr).each(function(i) {
      thisTbody.append($('tr[data-index="' + this + '"]', thisTable));
    });
 
    saveOrder();
  } else {
    saveOrder();
  }
 
  // Prevent clicking twice in the same row
  function updateRowLocks() {
    $('input[type="radio"]', thisQuestion).prop('disabled', false);
 
    $('input[type="radio"]:checked', thisQuestion).each(function(i) {
      var thisRow = $(this).closest('tr.answers-list');
      $('input[type="radio"]', thisRow).not(this).prop('disabled', true);
    });
  }
 
  updateRowLocks();
 
  $('input[type="radio"]', thisQuestion)
    .off('click.maxdiff')
    .on('click.maxdiff', function() {
      updateRowLocks();
    });
 
  // Fix up the row classes
  $('tr.answers-list', thisTable).removeClass('array1 array2').each(function(i) {
    $(this).addClass('array' + (2 - (i % 2)));
  });
}
 
function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}
 
$(document).ready(function() {
  maxDiff({QID}, true);
});
</script>
<style type="text/css">.ls-answers tbody .answertext {
  text-align: center;
}
</style>
 

Das Script habe ich aus deinem Tutorial und es versucht für meinen Fall anzupassen, damit es mir die Reihenfolge speichert. Soweit funktioniert auch alles wie gewünscht. Die Reihenfolge wird randomisiert und es wird in die short text Frage geschrieben.

Aber bei der folgenden Matrix-Frage scheitere ich. Ich nutze hier folgendes Script:
Code:
<script type="text/javascript" data-author="Tony Partner">
$(document).on('ready pjax:scriptcomplete',function(){
//Identify this question
var thisQuestion = $('#question{QID}');
var thisAnswerList = $('tr.answers-list:eq(0)', thisQuestion).parent();
// Retrieve the answer codes from the "maxDiff2order" question
var answerCodesString = "{maxDiff2order.NAOK}";
var answerCodes = answerCodesString.split('|');
//var answerCodes = '{maxDiff2order}'.split(',');
// Loop through the answer codes
$.each(answerCodes, function(i, val) {
// Move the answer item
$(thisAnswerList).append($('tr.answers-list[id$="X{QID}'+val+'"]', thisQuestion));
});
});
</script>
Jetzt funktioniert allerdings gar nichts mehr, wenn ich mir den Fragebogen über die Umfragevorschau anschaue. Auch die Randomisierung der MaxDiff-Frage und das Speichern der Reihenfolge wird jetzt nicht mehr ausgeführt. Die zweite Matrix-Frage ist auch extra auf einer neuen Seite im Fragebogen. So jetzt das noch seltsamere, teilweise funktioniert es, meist allerdings nicht. Warum verstehe ich bisher nicht. Es ändert sich auch teils, ohne das ich etwas an den Fragen ändere, sondern nur einen neuen Testlauf starte.

Viele Grüße

Please Log in to join the conversation.

More
1 day 5 hours ago #274228 by jelo
Vielleicht lädst Du den aktuell "kaputten" Fragebogen als LSS auch hoch. Sonst lassen sich Fehler schwerlich finden, die vielleicht aus einem Zusammenspiel von Veränderungen entstehen.

The meaning of the word "stable" for users
www.limesurvey.org/forum/development/117...ord-stable-for-users

Please Log in to join the conversation.

More
1 day 5 hours ago #274229 by Surveylab_KN
Hallo jelo,
ja klar, hatte ich leider vergessen.

File Attachment:

File Name: MaxDiff_Re...5733.lss
File Size:89.51 KB

Vielleicht lädst Du den aktuell "kaputten" Fragebogen als LSS auch hoch. Sonst lassen sich Fehler schwerlich finden, die vielleicht aus einem Zusammenspiel von Veränderungen entstehen.

 

Please Log in to join the conversation.

More
1 day 4 minutes ago - 1 day 1 minute ago #274230 by Joffm
Hallo,
so hier also mein Beispiel.

File Attachment:

File Name: limesurvey...33_J.lss
File Size:60.94 KB


Ich habe gar nicht viel geändert.
Nur:
Im  MaxDiff-script wird jetzt nicht eine Funktion aufgerufen - das fand ich immer schon merkwürdig - und es wird einfach das erzeugte Array in die folgende versteckte Te4xtfrage geschrieben.
Code:
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
 
function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}
 
 
  // Identify some elements
  var randomize=true;
  var qID='{QID}';
  var thisQuestion = $('#question'+qID);
  var thisTable = $('table.subquestion-list:eq(0)', thisQuestion);
  // Die folgende Textfrage wird angesprochen
  var hiddenQuestion = $(thisQuestion).nextAll('.text-short:eq(0)');
 
  // Assign a new question class
  $(thisQuestion).addClass('max-diff-array');
 
  // Move the columns
  $('thead tr:eq(0)', thisTable).prepend($('thead tr:eq(0) th:eq(1)', thisTable));
  $('tr.answers-list', thisTable).each(function(i){
  $('td.answer-item:eq(0)', this).prependTo(this);
  });
 
  // Random rows
  if(randomize) {
      var rowsArr=;
      $('tr.answers-list', thisTable).each(function(i){
          $(this).attr('data-index', i);
          rowsArr.push(i);
      });
      shuffleArray(rowsArr);
 
      $(rowsArr).each(function(i){
          $('tbody', thisTable).append($('tr[data-index="'+this+'"]', thisTable));
      });
 
       // Das erzeugte Array wird in die Textfrage geschrieben.    
      $('input:text', hiddenQuestion).val(rowsArr);
  }
 
  // Prevent clicking twice in the same row
  $('input[type="radio"]', thisQuestion).on('click', function () {
 
      $('input[type="radio"]', thisQuestion).prop('disabled', false);
      $('input[type="radio"]:checked', thisQuestion).each(function(i) {
          var thisRow = $(this).closest('tr.answers-list');
          $('input[type="radio"]', thisRow).not(this).prop('disabled', true);
      });
  });
 
  // Fix up the row classes
  var rowClass = 1;
  $('tr.answers-list', thisTable).each(function(i) {
      $(this).addClass('array'+(2-(i%2)));
  });
});
</script>
<style type="text/css">.ls-answers tbody .answertext {
    text-align: center;
  }
</style>[/i][/i]


Mehr nicht.
Und das script in der Matrix ist unverändert aus meinem Tutorial

Code:
<script type="text/javascript" data-author="Tony Partner">
  $(document).on('ready pjax:scriptcomplete',function(){
 
    //Identify this question
    var thisQuestion = $('#question{QID}');
    var thisAnswerList = $('tr.answers-list:eq(0)', thisQuestion).parent();
 
  // Retrieve the answer codes from the "randOrder" question
    var answerCodes = '{randOrder}'.split(',');
 
    // Loop through the answer codes
    $.each(answerCodes, function(i, val) {
      // Move the answer item
      $(thisAnswerList).append($('tr.answers-list[id$="X{QID}'+val+'"]', thisQuestion));
    });
  });
</script>


Dann gibt es dies:
 


Wichtig dabei: Die Codes der Matrix laufen von 0 - 4. Das kommt einfach aus dem MaxDiff-script, weil der benutzte Index auch so läuft.

Ich habe jetzt (noch) nicht Dein script untersucht, warum es nicht funktioniert.

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 1 day 1 minute ago by Joffm.

Please Log in to join the conversation.

Moderators: holchJoffmtpartner

Lime-years ahead

Online-surveys for every purse and purpose