Missing Data - Plot by Case

From Q
Jump to navigation Jump to search


Creates a chart showing the missing data by case in the data file. Each "column" represents a different variable, and the shading indicates missing values. The chart supports hover and zoom.

Example

In the example below, there are no missing values for Does respondent have mobile phone, a smattering for Work status and Age, and many for Occupation.

Usage

To run this test in Displayr, go to Insert > More > Missing Data > Plot by Case (in Q, go to Automate > Browse Online Library > Missing Data > Plot by Case).

In the object inspector, under Inputs > Variables select the variables you want to visualize, change any other settings, and click Calculate to run the function.

Options

Variables The variables to show in the chart. Each variable will be shown as a column in the chart.

Variable names Show variable names instead of labels.

Show number of cases missing Include the number of cases missing in the X axis labels.

Show percentage of cases missing Include the percentage of data missing in the X axis labels.

Fill color Color used to display missing cases.

Background color Color used to display non-missing cases.

Global font family Font family used in the all of the text elements. This can be overriden for specific text elements in the controls below.

Global font color Font color used in all the text elements in the chart. This can be overriden for specific text elements in the controls below.

Show hover text Show index of missing cases on hover. This may be quite slow if the number of missing cases is large.

Show data labels Show index of missing cases as data labels on the chart. This can be useful for using the chart when hover is not available. However, it is often not useful if the number of missing cases is large because labels will overlap.

Automatically set opacity If selected, the opacity of the lines showing missing cases will be automatically set. If the density of missing cases is high, is opacity be lowered to improve visibility. However, for some data sets it may be more appropriate to manually set the opacity.

Data label background opacity By default there is a background that is set to 1 so that the data labels can be easily seen above the chart lines. However, if the number of cases are few, so the filled areas are more rectangle like, it may be better to set the opacity to 0.

Title Optional title to show in chart.

Subtitle Optional subtitle to show in chart.

Footer Optional footer to show in chart.

X axis label orientation Whether to show the labels horizontally or vertically. If this is set to automatic, labels will be placed horizontally if there are less than 10 variables and vertically otherwise.

Wrap X axis label Whether labels should be wrapped across multiple lines if they are too long.

X axis label width (in characters) Maximum number of characters before a line is wrapped.

Customize margins Select this option to manually specify margin sizes (in pixels).

Code

var allow_control_groups = Q.fileFormatVersion() > 10.9;
font_families = !!Q.GetAvailableFontNames ? Q.GetAvailableFontNames() : ["Arial", "Arial Black", "Comic Sans MS",  "Courier New", "Georgia", "Impact", 
                 "Open Sans", "Tahoma", "Times New Roman", "Trebuchet MS", "Verdana"];

var heading_text = "Missing Data by Case";
if (!!form.setObjectInspectorTitle)
    form.setObjectInspectorTitle(heading_text, heading_text);
else 
    form.setHeading(heading_text);
if (allow_control_groups)
    form.group("Data Source")
form.dropBox({label: "Variables", name: "formVariables", multi: true, min_inputs: 1, required: true, types:["Variable"], prompt: "Choose variables to show in chart"});
form.checkBox({label: "Variable names", name: "formNames", default_value: false, prompt: "Show variable names instead of variable labels"});
form.checkBox({label: "Tidy labels", name: "formTidyLabels", default_value: true, prompt: "Extract common prefixes to simplify labels"});
form.checkBox({label: "Show hover text", name: "formShowHover", default_value: false, prompt: "Show case number on hover. This may be slow if the number of missing cases is very large."});
form.checkBox({label: "Show number of cases missing", name: "formShowCounts", default_value: true, prompt: "Include a count of the number of cases missing in the variable labels"});
form.checkBox({label: "Show percentage of cases missing", name: "formShowPercentages", default_value: false, prompt: "Include the percentages of cases missing in the variable labels"});

if (allow_control_groups)
    form.page("Chart");
if (allow_control_groups)
form.group("APPEARANCE");
form.colorPicker({name: "formFillColor", label: "Fill color", default_value: "#5C9AD3", prompt: "Color for displaying missing cases"});
var autoOpacity = form.checkBox({name: "formAutoFillOpacity", label: "Automatically set opacity", default_value: true, prompt: "Opacity is automatically reduced to improve visibility if there are more missing cases. However, if the density of missing cases is very high it may be better to manually set the opacity even lower."}).getValue();
if (!autoOpacity)
    form.numericUpDown({name: "formFillOpacity", label: "Fill opacity", default_value: 0.5, minimum: 0.0, maximum: 1.0, increment: 0.05});
form.colorPicker({name: "formBGColor", label: "Background color", default_value: "#E6E6E6"});

if (allow_control_groups)
    form.group("FONT");
var qGlobalFontFamily = form.comboBox({name: "formGlobalFontFamily", label: "Global font family", alternatives: font_families, default_value: "Arial", editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}).getValue();
var qGlobalFontColor = form.colorPicker({name: "formGlobalFontColor", label: "Global font color", default_value: "#2C2C2C"}).getValue();
var qGlobalFontUnit = form.comboBox({name: "formFontUnits", label: "Font units", default_value: "pt", alternatives: ["px", "pt"], prompt: "Specify font sizes in pt or px"}).getValue();

if (allow_control_groups)
    form.group("DATA LABELS");
var qDataLabelShow = form.checkBox({name: "formDataLabelShow", label: "Show data labels", default_value: false, prompt: "Show index of missing cases on chart"}).getValue();
if (qDataLabelShow)
{
    form.comboBox({name: "formDataLabelFontFamily", label: "Data label font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
    form.colorPicker({name: "formDataLabelFontColor", label: "Data label font color", default_value: qGlobalFontColor});
    form.numericUpDown({name: "formDataLabelFontSize", label: "Data label font size", default_value: 7.5, increment: 0.5});
    form.numericUpDown({name: "formDataLabelBgOpacity", label: "Data label background opacity", default_value: 0.5, minimum_value: 0.0, maximum_value: 1.0, increment: 0.05});
}

if (allow_control_groups)
        form.group('Title');
var qTitle = form.textBox({name:"formTitle", label:"Title", required:false, default_value: "Missing values by case"}).getValue();
if (qTitle != "")
{
    form.comboBox({name: "formTitleFontFamily", label: "Title font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
    form.colorPicker({name: "formTitleFontColor", label: "Title font color", default_value: qGlobalFontColor});
    form.numericUpDown({name:"formTitleFontSize", label:"Title font size", default_value: 12, increment: 0.5});
}

var qSubtitle = form.textBox({name:"formSubtitle", label:"Subtitle", required:false}).getValue();
if (qSubtitle != "")
{
    form.comboBox({name: "formSubtitleFontFamily", label: "Subtitle font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
    form.colorPicker({name: "formSubtitleFontColor", label: "Subtitle font color", default_value: qGlobalFontColor});
    form.numericUpDown({name:"formSubtitleFontSize", label:"Subtitle font size", default_value: 9, increment: 0.5});
}

var qFooter = form.textBox({name:"formFooter", label:"Footer", required:false}).getValue();
if (qFooter != "")
{
    form.comboBox({name: "formFooterFontFamily", label: "Footer font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
    form.colorPicker({name: "formFooterFontColor", label: "Footer font color", default_value: qGlobalFontColor});
    form.numericUpDown({name:"formFooterFontSize", label:"Footer font size", default_value: 6, increment: 0.5});
    var footerWrapOpt = form.checkBox({name: "formFooterWrap", label: "Wrap footer", default_value: false}).getValue();
    if (footerWrapOpt)
        form.numericUpDown({name: "formFooterWrapNchar", label: "Footer width (in characters)", default_value: 100, minimum: 5, increment: 5, maximum: 5000});
}

if (allow_control_groups)
    form.group("X AXIS")
form.comboBox({name: "formXAxisTickFontFamily", label: "X axis label font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
form.colorPicker({name: "formXAxisTickFontColor", label: "X axis label font color", default_value: qGlobalFontColor});
form.numericUpDown({name:"formXAxisTickFontSize", label: "X axis label font size", default_value: 7.5, increment: 0.5});
form.comboBox({name: "formXAxisTickOrientation", label: "X axis label orientation", alternatives: ["Automatic", "Horizontal", "Diagonal", "Vertical"], default_value: "Automatic"})
var xtickWrapOpt = form.checkBox({name: "formXAxisTickWrap",  label: "Wrap X axis label", default_value: true}).getValue();
if (xtickWrapOpt)
    form.numericUpDown({name: "formXAxisTickWrapNchar", label: "X axis label width (in characters)", default_value: 21});

if (allow_control_groups)
    form.group("Y AXIS")
form.comboBox({name: "formYAxisTickFontFamily", label: "Y axis label font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
form.colorPicker({name: "formYAxisTickFontColor", label: "Y axis label font color", default_value: qGlobalFontColor});
form.numericUpDown({name:"formYAxisTickFontSize", label:"Y axis label font size", default_value: 7.5, increment: 0.5});
   
if (allow_control_groups)
    form.group("HOVERTEXT");
form.comboBox({name: "formHoverTextFontFamily", label: "Hover text font family", alternatives: font_families, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
form.colorPicker({name: "formHoverTextFontColor", label: "Hover text font color", default_value: "#FFFFFF"});
form.numericUpDown({name:"formHoverTextFontSize", label:"Hover text font size", default_value: 9, increment: 0.5});


if (allow_control_groups)
    form.group("MARGINS");
var qCustomMargin = form.checkBox({name: "formCustomMargin", label: "Customize margins", default_value: false, prompt: "Select to manually specify margin sizes in pixels"}).getValue();
if (qCustomMargin)
{
   form.numericUpDown({name: "formMarginTop", label: "Top", default_value: 20, increment: 1, minimum: 0, maximum: 1000});
   form.numericUpDown({name: "formMarginLeft", label: "Left", default_value: 80, increment: 1, minimum: 0, maximum: 1000});
   form.numericUpDown({name: "formMarginBottom", label: "Bottom", default_value: 20, increment: 1, minimum: 0, maximum: 1000});
   form.numericUpDown({name: "formMarginRight", label: "Right", default_value: 60, increment: 1, minimum: 0, maximum: 1000});
}
library(flipFormat)
library(flipStandardCharts)

WarnIfVariablesSelectedFromMultipleDataSets()

data <- as.data.frame(formVariables, check.names = FALSE)
names(data) <- if (!isTRUE(get0("formNames"))) Labels(formVariables) else Names(formVariables)
if (formTidyLabels)
    names(data) <- flipFormat::ExtractCommonPrefix(names(data))$shortened.labels

missing.cases <- MissingCasesPlot(data, subset = QFilter,
    fill.color = formFillColor,
    fill.opacity = get0("formFillOpacity"),
    base.color = formBGColor,
    show.counts.missing = formShowCounts,
    show.percentages.missing = formShowPercentages,
    tooltip.show = formShowHover,
    global.font.family = formGlobalFontFamily,
    global.font.color = formGlobalFontColor,
    data.label.show = formDataLabelShow,
    data.label.font.family = get0("formDataLabelFontFamily"),
    data.label.font.color = get0("formDataLabelFontColor"),
    data.label.font.size = get0("formDataLabelFontSize"),
    data.label.bg.opacity = get0("formDataLabelBgOpacity"),
    title = formTitle,
    title.font.family = get0("formTitleFontFamily"),
    title.font.color = get0("formTitleFontColor"),
    title.font.size = get0("formTitleFontSize"),
    subtitle = formSubtitle,
    subtitle.font.family = get0("formSubtitleFontFamily"),
    subtitle.font.color = get0("formSubtitleFontColor"),
    subtitle.font.size = get0("formSubtitleFontSize"),
    footer = formFooter,
    footer.font.family = get0("formFooterFontFamily"),
    footer.font.color = get0("formFooterFontColor"),
    footer.font.size = get0("formFooterFontSize"),
    footer.wrap = get0("formFooterWrap", ifnotfound = FALSE),
    footer.wrap.nchar = get0("formFooterWrapNchar"),
    x.tick.font.family = formXAxisTickFontFamily,
    x.tick.font.color = formXAxisTickFontColor,
    x.tick.font.size = formXAxisTickFontSize,
    x.tick.angle = switch(get0("formXAxisTickOrientation"), Automatic = NULL, Horizontal = 0, Diagonal = 45, Vertical = 90),
    x.tick.label.wrap = get0("formXAxisTickWrap"),
    x.tick.label.wrap.nchar = get0("formXAxisTickWrapNchar"),
    y.tick.font.family = formYAxisTickFontFamily,
    y.tick.font.color = formYAxisTickFontColor,
    y.tick.font.size = formYAxisTickFontSize,
    hovertext.font.family = formHoverTextFontFamily,
    hovertext.font.color = formHoverTextFontColor,
    hovertext.font.size = formHoverTextFontSize,
    margin.top = get0("formMarginTop"),
    margin.bottom = get0("formMarginBottom"),
    margin.left = get0("formMarginLeft"),
    margin.right = get0("formMarginRight"),
    font.unit = formFontUnits)