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.