Example surveys¶
This notebook contains code for creating variations of questions and combining them into surveys in edsl
.
Question scenarios
Combining questions
Seeding questions
Survey rules
Survey contexts and administration
from edsl.questions import QuestionLinearScale, QuestionCheckBox, QuestionYesNo, QuestionMultipleChoice, QuestionFunctional
from edsl.questions.compose_questions import compose_questions
from edsl import Agent, Survey, Scenario
Question scenarios¶
Many times we want to re-administer a question with a different parameter or input. We can do this by creating "scenarios" of a question:
items = ["groceries", "clothes", "shoes", "electronics", "home furnishings", "books", "sporting equipment", "wellness items"]
q_shopping = QuestionLinearScale(
question_name = "q_shopping",
question_text = "On a scale of 0-10, how much do you typically enjoy shopping for {{item}}? (0 = Not at all, 10 = Very much)",
question_options = [0,1,2,3,4,5,6,7,8,9,10]
)
scenarios = [Scenario({"item":item} )for item in items]
scenarios
[{'item': 'groceries'}, {'item': 'clothes'}, {'item': 'shoes'}, {'item': 'electronics'}, {'item': 'home furnishings'}, {'item': 'books'}, {'item': 'sporting equipment'}, {'item': 'wellness items'}]
We can use the by()
method to create an instance of our question for each scenario parameter:
q_shopping.by(scenarios)
Jobs(survey=Survey(questions=[QuestionLinearScale(question_text = 'On a scale of 0-10, how much do you typically enjoy shopping for {{item}}? (0 = Not at all, 10 = Very much)', question_options = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], question_name = 'q_shopping', short_names_dict = {}, option_labels = None)], name=None), agents=[], models=[], scenarios=[{'item': 'groceries'}, {'item': 'clothes'}, {'item': 'shoes'}, {'item': 'electronics'}, {'item': 'home furnishings'}, {'item': 'books'}, {'item': 'sporting equipment'}, {'item': 'wellness items'}])
Combining questions¶
We can combine questions to administer them at once with the add_question()
method:
q1 = QuestionYesNo(
question_name = "fit",
question_text = "Do you find it difficult to shop for clothes that fit you?"
)
q2 = QuestionMultipleChoice(
question_name = "online",
question_text = "How often do you shop for clothes online?",
question_options = ["Never", "Rarely", "Occasionally", "Often"]
)
q1.add_question(q2)
Survey(questions=[QuestionYesNo(question_text = 'Do you find it difficult to shop for clothes that fit you?', question_options = ['Yes', 'No'], question_name = 'fit', short_names_dict = {}), QuestionMultipleChoice(question_text = 'How often do you shop for clothes online?', question_options = ['Never', 'Rarely', 'Occasionally', 'Often'], question_name = 'online', short_names_dict = {})], name=None)
result = q1.add_question(q2).run()
result.select("fit","online").print()
┏━━━━━━━━┳━━━━━━━━━━━━━━┓ ┃ answer ┃ answer ┃ ┃ .fit ┃ .online ┃ ┡━━━━━━━━╇━━━━━━━━━━━━━━┩ │ Yes │ Occasionally │ └────────┴──────────────┘
We can also combine any-sized sets of questions in surveys:
q_factors = QuestionCheckBox(
question_name = "q_factors",
question_text = "Which of the following factors are important to you in making decisions about clothes shopping? Select all that apply.",
question_options = [
"Price",
"Quality",
"Brand Reputation",
"Style and Design",
"Fit and Comfort",
"Customer Reviews and Recommendations",
"Ethical and Sustainable Practices",
"Return Policy",
"Convenience",
"Other"
]
)
survey = Survey(
questions = [
q_shopping,
q_factors
]
)
survey.by(scenarios)
Jobs(survey=Survey(questions=[QuestionLinearScale(question_text = 'On a scale of 0-10, how much do you typically enjoy shopping for {{item}}? (0 = Not at all, 10 = Very much)', question_options = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], question_name = 'q_shopping', short_names_dict = {}, option_labels = None), QuestionCheckBox(question_name = 'q_factors', question_text = 'Which of the following factors are important to you in making decisions about clothes shopping? Select all that apply.', min_selections = None, max_selections = None, question_options = ['Price', 'Quality', 'Brand Reputation', 'Style and Design', 'Fit and Comfort', 'Customer Reviews and Recommendations', 'Ethical and Sustainable Practices', 'Return Policy', 'Convenience', 'Other'], short_names_dict = {})], name=None), agents=[], models=[], scenarios=[{'item': 'groceries'}, {'item': 'clothes'}, {'item': 'shoes'}, {'item': 'electronics'}, {'item': 'home furnishings'}, {'item': 'books'}, {'item': 'sporting equipment'}, {'item': 'wellness items'}])
result = survey.by(scenarios).run()
result.select("scenario.*","q_shopping","q_factors").print()
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ scenario ┃ answer ┃ answer ┃ ┃ .item ┃ .q_shopping ┃ .q_factors ┃ ┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ groceries │ 5 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ clothes │ 5 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices', 'Convenience'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ shoes │ 5 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices', 'Convenience'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ electronics │ 6 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Customer Reviews and │ │ │ │ Recommendations', 'Ethical and Sustainable Practices'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ home furnishings │ 7 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ books │ 9 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ sporting equipment │ 7 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices'] │ ├────────────────────┼─────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ wellness items │ 5 │ ['Quality', 'Style and Design', 'Fit and Comfort', 'Ethical and Sustainable │ │ │ │ Practices'] │ └────────────────────┴─────────────┴──────────────────────────────────────────────────────────────────────────────┘
Seeding questions¶
If we want an agent to refer to a prior response in answering a new question, we can seed the new question with a response to a prior question:
q_green_eggs_ham = QuestionYesNo(
question_name = "green_eggs_ham",
question_text = "Do you like {{food}}?"
)
q_sam = QuestionYesNo(
question_name = "sam",
question_text = "You were previously asked: '" + q_green_eggs_ham.question_text
+ "' You responded: '{{green_eggs_ham}}'. Are you Sam I Am?"
)
q_ham_sam = compose_questions(q_green_eggs_ham, q_sam).by(Scenario({"food":"green eggs and ham"}))
q_ham_sam
Jobs(survey=Survey(questions=[QuestionFunctional(question_name = 'green_eggs_ham_sam', func = <function compose_questions.<locals>.combo at 0x2869931a0>, question_text = 'functional')], name=None), agents=[], models=[], scenarios=[{'food': 'green eggs and ham'}])
Survey rules¶
We can add rules to a survey, such as skip logic and stop logic. Here we at a stop rule to end the survey at the first question if the response is "No":
survey_ham_sam = (q_green_eggs_ham
.add_question(q_sam)
.add_stop_rule("green_eggs_ham", "green_eggs_ham == 'no'")
)
survey_ham_sam
Survey(questions=[QuestionYesNo(question_text = 'Do you like {{food}}?', question_options = ['Yes', 'No'], question_name = 'green_eggs_ham', short_names_dict = {}), QuestionYesNo(question_text = 'You were previously asked: 'Do you like {{food}}?' You responded: '{{green_eggs_ham}}'. Are you Sam I Am?', question_options = ['Yes', 'No'], question_name = 'sam', short_names_dict = {})], name=None)
Note that adding the questions creates a Survey, to which we append the stop rule. We can also explicitly create a Survey with the stop rule (these are equivalent):
survey_ham_sam_v2 = Survey([q_green_eggs_ham, q_sam]).add_stop_rule("green_eggs_ham", "green_eggs_ham == 'no'")
survey_ham_sam_v2
Survey(questions=[QuestionYesNo(question_text = 'Do you like {{food}}?', question_options = ['Yes', 'No'], question_name = 'green_eggs_ham', short_names_dict = {}), QuestionYesNo(question_text = 'You were previously asked: 'Do you like {{food}}?' You responded: '{{green_eggs_ham}}'. Are you Sam I Am?', question_options = ['Yes', 'No'], question_name = 'sam', short_names_dict = {})], name=None)
Survey contexts and administration¶
We can explore relationships between survey responses and the contexts or conditions under which a survey was "administered". For example, do responses vary depending on whether the questions asked in an anonymous paper or online survey, by a researcher or in a focus group composed of diverse or similar individuals?
This can be explored in edsl
by adding context about the survey administration to the question text and/or agent traits:
Do you exercise every day? (You are being asked this question in a focus group of peers.)
See an example notebook here.