// Numbas version: finer_feedback_settings
{"name": "ggplots with moneydemand", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "
Mark code provided by the student by running it and a series of validation and marking tests.
\nThe validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.
\nMarking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.
\nYou can optionally show the student the STDOUT and/or STDERR when running their code.
\nYou can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.
", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output: {escape_html(main_stdout)}\")\n);\nassert(main_result[\"success\"],\n warn(\"\"\"There was an error in your code.\"\"\");\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code: {escape_html(main_result[\"stderr\"])}\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error: {escape_html(r[\"stderr\"])}\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\n fail(\"\"\"There was an error running the test {name}: {escape_html(r[\"stderr\"])}\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\nif(studentAnswer=nothing,\n []\n,\n [run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n )]\n)\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"{escape_html(postamble_result[\"stdout\"])}\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble: {escape_html(postamble_result[\"stderr\"])}\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "The result of running the student's code and the preamble, without any tests.
\nNormally used to detect errors in the student's code.
", "definition": "code_result[3]"}, {"name": "marking_results", "description": "The results of running the marking tests.
", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "The results of running the validation tests.
", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "Show STDOUT if allowed.
\nCheck the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.
", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output: {escape_html(main_stdout)}\")\n);\nassert(main_result[\"success\"],\n warn(\"\"\"There was an error in your code.\"\"\");\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code: {escape_html(main_result[\"stderr\"])}\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.
", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error: {escape_html(r[\"stderr\"])}\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.
", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\n fail(\"\"\"There was an error running the test {name}: {escape_html(r[\"stderr\"])}\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.
", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "The code blocks to run.
\nIn order, they are:
\n\n- 0 - The matplotlib hack preamble (in Python, make sure matplotlib plots are displayed)
\n- 1 - Set passed-in variables
\n- 2 - Preamble
\n- 3 - The student's code
\n- 4 - Postamble
\n- 5 - The matplotlib hack postamble
\n- Marking tests
\n- Validation tests
\n
", "definition": "if(studentAnswer=nothing,\n []\n,\n [run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n )]\n)"}, {"name": "code_result", "description": "The results of the code blocks: a list with an entry corresponding to each block of code.
", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "The stdout from the student's code.
", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)
", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "The result of running the preamble block.
", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "The STDERR produced by the preamble block.
", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "The result of running the postamble.
", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "The STDERR produced by the postamble block.
", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "Show the STDOUT from the postamble, if there is any.
", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"{escape_html(postamble_result[\"stdout\"])}\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble: {escape_html(postamble_result[\"stderr\"])}\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.
\nThis code clears the matplotlib output, if matplotlib has been loaded.
", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "A hack to show any figures produced with matplotlib in the stdout.
", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "The result of running the matplotlib hack.
", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.
", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "Any images produced by the code blocks.
", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "Show the images produced by the code.
", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.
If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n\n- The name of the test, shown to the student above any feedback.
\n- The proportion of the credit available for the part to award if this test is passed.
\n- The code to run.
\n
", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:
\n\n- A name which will be shown to the student if the test fails.
\n- The code to run.
\n
", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "ggplots with moneydemand", "tags": [], "metadata": {"description": "\n- This question assesses students' ability to:\n
\n- create basic visualisation of multivariate data using ggplot2, and
\n- identify errors and issues with ggplot2 code and fix them accordingly.
\n
\n \n- The students submit code to each part. It is envisioned that they will try the code in RStudio, and only submit to Numbas when they are satisfied with the resulting visualisation or output.
\n- As of 2026-02-24, this question is not randomised.
\n
", "licence": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International"}, "statement": "You will need to use ggplot2 functions and the money demand dataset for this question. Download moneydemand.csv from the assignment page on Canvas. The dataset is a multivariate yearly time series with the following variables:
\n\nyear: year, from 1879 to 1974 \nlogM: logarithm of quantity of money \nlogYp: logarithm of real permanent income \nRs: short term interest rate \nRm: rate of return on money \nRl: not documented in the sources \nlogSpp: logarithm of an operational measure of the variability of the rate of price changes \n
", "advice": "library(ggplot2)
library(readr)
\nggplot(md, aes(x = logM, y = logYp)) +
geom_point() +
labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")
\nggplot(md, aes(x = year, y = Rs)) +
geom_line() +
geom_point() +
labs(y = \"short term interest rate\")
\nggplot(md, aes(x = Rm)) +
geom_histogram(binwidth = 0.3) +
labs(x = \"rate of return on money\")
\nggplot(md, aes(x = year, y = logYp, colour = logSpp)) +
geom_line() +
scale_colour_viridis_b() +
labs(y = \"log(real permanent income)\", colour = \"rate variability\")
\nggplot(md, aes(x = Rs, y = logM, size = Rm)) +
geom_point() +
labs(
x = \"short term interest rate\",
y = \"log(quantity of money)\",
size = \"rate of return on money\"
)
", "rulesets": {}, "extensions": ["programming"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true, "j": false}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Write code to load the packages ggplot2 and readr.
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "library(ggplot2)\nlibrary(readr)", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "si <- names(sessionInfo()$otherPkgs)", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct packages via library()\", \n 1, \n \"'readr' %in% si && 'ggplot2' %in% si\"]\n]", "validation_tests": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "variables": "dict()"}}, {"type": "information", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Run the above code i.e. copy your answers to RStudio console and press Enter. Next, run the following code to create the data frame md:
\nmd <- read_csv(\"moneydemand.csv\")
"}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "The following code produces a scatterplot of logYp against logM:
\nmd |> ggplot() +
geom_point(aes(x = logM, y = logYp)) +
labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")
\nWrite code to simultaneously do the following:
\n\n- create the same scatterplot, but with the use of the
aes() function in ggplot(), and \n- keep the axis labels the same as above.
\n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = logM, y = logYp)) + \n geom_point() + \n labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct place of aes()\", \n 1, \n \"identical(as.character(student_answer$mapping)[1:2], c('~logM', '~logYp')) &&\n identical(names(student_answer$mapping)[1:2], c('x', 'y'))\"],\n [\"Correct labels\",\n 1,\n \"identical(str_to_lower(student_answer$labels$x), 'log(quantity of money)') &&\n identical(str_to_lower(student_answer$labels$y), 'log(real permanent income)')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"],\n [\"Is a point plot\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint')\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "We would like to make a point and line plot of Rs over year. However, the following code produces an error:
\nggplot(md) + geom_line(aes(x = year, y = Rs)) + geom_point()
\nWrite code to simultaneously do the following:
\n\n- fix the error and create the correct plot, and
\n- label the y-axis
\"short term interest rate\". \n
", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "aes in both geoms", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md) + \n geom_line(aes(x = year, y = Rs)) + \n geom_point(aes(x = year, y = Rs)) + \n labs(y = \"short term interest rate\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()", "postamble_feedback_whitespace": false, "tests": "[\n [\"both geoms\", \n 1, \n \"identical(\n sort(sapply(student_answer$layers, function(x) class(x$geom)[1])), \n c('GeomLine', 'GeomPoint')\n )\"],\n [\"correct places of aes\", \n 1, \n \"identical(as.character(student_answer$layers[[1]]$mapping), c('~year', '~Rs')) &&\n identical(as.character(student_answer$layers[[2]]$mapping), c('~year', '~Rs')) &&\n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y')) &&\n identical(names(student_answer$layers[[2]]$mapping), c('x', 'y'))\n \"],\n [\"correct y-axis label\",\n 1,\n \"identical(student_answer$labels$y, 'short term interest rate')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = year, y = Rs)) + \n geom_line() + \n geom_point() + \n labs(y = \"short term interest rate\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)", "postamble_feedback_whitespace": false, "tests": "[\n [\"both geoms\", \n 1, \n \"identical(\n sort(sapply(student_answer$layers, function(x) class(x$geom)[1])), \n c('GeomLine', 'GeomPoint')\n )\n \"],\n [\"correct place of aes\", \n 1, \n \"identical(as.character(student_answer$mapping)[1:2], c('~year', '~Rs')) && \n identical(names(student_answer$mapping)[1:2], c('x', 'y'))\n \"],\n [\"correct y-axis label\",\n 1,\n \"identical(str_to_lower(student_answer$labels$y), 'short term interest rate')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Write code to simultaneously do the following:
\n\n- make a histogram of
Rm, \n- set a sensible
binwidth so that the number of bins is between 15 and 20, and \n- label the x-axis
\"rate of return on money\", and \n
\n", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rm)) + \n geom_histogram(binwidth = 0.3) + \n labs(x = \"rate of return on money\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": true, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nbw <- student_answer$layers[[1]]$stat_params$binwidth", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct geom (histogram)\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomBar') && \n identical(class(student_answer$layers[[1]]$stat)[[1]], 'StatBin')\"\n ],\n [\"correct x-axis label\",\n 1,\n \"identical(str_to_lower(student_answer$labels$x), 'rate of return on money')\"],\n [\"Appropriate binwidth\", \n 1, \n \"!is.null(bw) && bw >= 0.3 && bw <= 0.5\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "4", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "The following code attempts to plot logYp over year and coloured by logSpp:
\nggplot(md, aes(x = year, y = logYp, fill = logSpp)) + geom_line()
\nHowever, running the code returns a warning, and no colours were displayed.
\nWrite code to simultaneously do the following:
\n\n- fix the above issue,
\n- incorporate a binned colour palette for
logSpp, and \n- label the y-axis and colour scale
\"log(real permanent income)\" and \"rate variability\", respectively. \n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = year, y = logYp, colour = logSpp)) + \n geom_line() + \n scale_colour_viridis_b() +\n labs(y = \"log(real permanent income)\", colour = \"rate variability\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\ncolour_list <- student_answer$scales$scales", "postamble_feedback_whitespace": false, "tests": "[\n [\"labels\", \n 1, \n \"identical(str_to_lower(student_answer$labels$y), 'log(real permanent income)') &&\n identical(str_to_lower(student_answer$labels$colour), 'rate variability')\n \"\n ],\n [\"colour as the correct aesthetic\",\n 1,\n \"xor(\n identical(names(student_answer$mapping)[3], 'colour'), \n identical(names(student_answer$layers[[1]]$mapping)[3], 'colour')\n )\"\n ],\n [\"used a colour palette\",\n 1,\n \"(length(colour_list) == 1) && ('colour' %in% colour_list[[1]]$aesthetics)\"\n ],\n [\"binned scale\",\n 1,\n \"('ScaleBinned' %in% class(colour_list[[1]]))\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"],\n [\"Is a line plot\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomLine')\"],\n [\"logSpp as the third variable\",\n \"xor(\n identical(as.character(student_answer$mapping)[3], '~logSpp'), \n identical(as.character(student_answer$layers[[1]]$mapping)[3], '~logSpp')\n )\"\n ]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Write code to simultaneously do the following:
\n\n- make a scatterplot of
logM against Rs, \n- use an appropriate non-colour aesthetic of the points representing
Rm (meaning that the plot stays the same when printed on grey scale), and \n- label the x-axis, y-axis and the aesthetic scale
\"short term interest rate\", \"log(quantity of money)\", and \"rate of return on money\", respectively. \n
", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "opacity", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rs, y = logM, alpha = Rm)) + \n geom_point() +\n labs(\n x = \"short term interest rate\", \n y = \"log(quantity of money)\", \n alpha = \"rate of return on money\"\n )", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels", "postamble_feedback_whitespace": false, "tests": "[\n [\"aesthetic\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping), c('~Rs', '~logM', '~Rm')), \n identical(as.character(student_answer$layers[[1]]$mapping), c('~Rs', '~logM', '~Rm'))\n ) && \n xor(\n identical(names(student_answer$mapping), c('x', 'y', 'alpha')), \n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y', 'alpha'))\n )\"\n ],\n [\"labels & point plot\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint') &&\n identical(str_to_lower(sal$x), 'short term interest rate') &&\n identical(str_to_lower(sal$y), 'log(quantity of money)') &&\n identical(str_to_lower(sal$alpha), 'rate of return on money')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rs, y = logM, size = Rm)) + \n geom_point() +\n labs(\n x = \"short term interest rate\", \n y = \"log(quantity of money)\", \n size = \"rate of return on money\"\n )", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels", "postamble_feedback_whitespace": false, "tests": "[\n [\"aesthetic\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping), c('~Rs', '~logM', '~Rm')), \n identical(as.character(student_answer$layers[[1]]$mapping), c('~Rs', '~logM', '~Rm'))\n ) && \n xor(\n identical(names(student_answer$mapping), c('x', 'y', 'size')), \n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y', 'size'))\n )\"\n ],\n [\"labels & point plot\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint') &&\n identical(str_to_lower(sal$x), 'short term interest rate') &&\n identical(str_to_lower(sal$y), 'log(quantity of money)') &&\n identical(str_to_lower(sal$size), 'rate of return on money')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "Clement Lee", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/21320/"}], "resources": []}]}], "contributors": [{"name": "Clement Lee", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/21320/"}]}