Tutorials › Exam PA - Predictive Analytics › Selecting Columns for Focused Inspection

Exam PA · Data Structures and Exploratory Summaries · Tutorial 104 of 966

Selecting Columns for Focused Inspection

Use R’s column-selection operators deliberately so focused inspection returns the structure you need.

Beginner 10 min read

What You'll Learn

  • Select one or several columns by name or position with square brackets
  • Distinguish a one-column data frame from an extracted column
  • Use double brackets and the dollar operator for direct column extraction
  • Select a column using a name stored in an R object
  • Avoid accidental dimension dropping and partial name matching
  • Recognize that extracted columns may retain list or matrix structure

Why Column Selection Needs Care

During data exploration, a data frame may contain many fields, while a particular question concerns only a few. Selecting those columns makes it easier to inspect the relevant inputs without changing the underlying data. In R, however, the result depends not only on which columns are selected but also on how they are selected.

A focused selection can return a smaller data frame or the contents of one column. These results may print similarly, but they are not interchangeable in later R code. The key distinction is between selecting a column as a component of a data frame and extracting that component itself. This practical skill supports data exploration work aligned with the SOA Exam PA (Predictive Analytics) syllabus.

Definition: In R, a data frame is a tabular object whose columns are components. Single-bracket indexing, such as df["amount"], selects columns while generally retaining a data frame. Double-bracket indexing, such as df[["amount"]], and the dollar operator, such as df$amount, extract a column component. With ordinary atomic-vector columns, extraction returns a vector; with list- or matrix-valued columns, it preserves the column’s underlying type.

One or Several Columns with Square Brackets

A data frame has two dimensions, so square-bracket indexing can specify rows and columns: the expression before the comma selects rows, and the expression after it selects columns. To select every row, leave the part before the comma blank. Column names or positions can then be supplied after the comma.

For example, suppose a hypothetical claims table is constructed as follows:

Code: claims <- data.frame(claim_id = c(501, 502, 503, 504), paid = c(1200, 0, 875, 2100), channel = c("web", "agent", "web", "broker"), flagged = c(TRUE, FALSE, FALSE, TRUE))

The expression claims[, c("paid", "channel")] selects all rows and the two named columns. The result remains a data frame with four rows and two columns. Using claims[c("paid", "channel")] also selects those columns and retains a data frame; when the row position is omitted in this form, R selects all rows.

Single brackets also accept column positions. For this table, claims[, c(2, 3)] selects the second and third columns, in that order. Names are usually easier to read and less vulnerable to errors if the column order changes. Positions can be useful when they are specifically required, but should be checked against the current column order.

Worked Example: Keep a Focused Two-Column Table

An analyst wants to inspect the paid amount and channel for every record in the hypothetical claims table above, in that order. Select the columns and state the result’s dimensions and values.

Method. Use single-bracket indexing with a character vector of column names: claims[c("paid", "channel")]. This selects two components while retaining their tabular arrangement.

The names vector is c("paid", "channel"), so the selected columns are ordered paid first and channel second. No row selection was specified, so all four records remain. The result has four rows and two columns:

paidchannel
1200web
0agent
875web
2100broker

Check. The selected columns appear in the requested order, and each has four entries, matching the four input rows. A common mistake is to select claims[2:3] on the assumption that those positions always mean paid and channel. They do in this particular table, but the named selection states the intended fields directly and remains clearer if columns are rearranged.

One Column: Data Frame or Extracted Component?

Selecting a single column is where a common source of confusion arises. claims["paid"] uses one set of square brackets and returns a one-column data frame. By contrast, claims[["paid"]] and claims$paid extract the column component. Since paid is an ordinary numeric column here, those latter expressions return a numeric vector.

The two-dimensional form claims[, "paid"] also selects the column, but by default R may simplify a one-column result by dropping the table dimension. For this ordinary data frame, it therefore returns a numeric vector. To retain a data frame in this form, specify drop = FALSE: claims[, "paid", drop = FALSE].

The reason these forms differ follows from the object and indexing operations. A data frame is built from columns arranged as a table. Single brackets select components but keep the result in a table-like container. Double brackets select one component from the data frame’s underlying list of columns. In two-dimensional indexing, R’s default dropping behavior can remove a dimension when only one column is selected; setting drop = FALSE prevents that simplification. Thus the choice of brackets and the drop setting determine whether the result is a table or an extracted component.

Worked Example: Preserve the Table or Extract Its Values

A reviewer needs to inspect all four paid amounts, then provide a one-column data frame to a function that expects tabular input. Determine which selection to use for each task and verify the returned forms.

Step 1: Extract the amounts. Use claims[["paid"]]. Because paid is an ordinary numeric-vector column, the result is the vector c(1200, 0, 875, 2100). The dollar form claims$paid returns the same vector for this exact column name.

Step 2: Keep a one-column table. Use claims["paid"], or use claims[, "paid", drop = FALSE]. Each returns a data frame with four rows and one column named paid. The values, in row order, are 1200, 0, 875, and 2100.

Step 3: Compare the forms. The extracted result contains the column’s values as a component; the retained result contains a table with a column named paid. The values and their order agree, but the result structures differ.

Check. Both outputs contain four paid amounts, so no records were removed. The one-column table has one column because only paid was requested. A common mistake is to use claims[, "paid"] when a downstream operation specifically requires a data frame. The correction is to use claims[, "paid", drop = FALSE] or claims["paid"].

Direct Extraction with Names and Positions

Double brackets are useful when one column is needed as a component. A name can be placed inside the brackets, as in claims[["channel"]], or a position can be used, as in claims[[3]]. Both refer to the third column in this particular table. The extracted values are c("web", "agent", "web", "broker").

The dollar operator offers a compact alternative when the column name is written directly in the expression: claims$channel. It is convenient for a fixed, unambiguous name. Unlike double brackets, the dollar operator does not take a name stored in another object as the name to look up. For a computed or variable column name, use double brackets.

Worked Example: Select a Column Named in an R Object

A reporting script receives a field name in the character object field <- "flagged". The analyst must select that field without hard-coding its name into the indexing expression, then check its values and keep the column as a data frame for a tabular handoff.

Step 1: Extract using the stored name. Use claims[[field]]. R evaluates field to the character value "flagged", then extracts that named component. Since flagged is an ordinary logical-vector column, the result is c(TRUE, FALSE, FALSE, TRUE).

Step 2: Keep a table instead. Use claims[field]. The character value in field selects the column, and single brackets retain a one-column data frame. Alternatively, claims[, field, drop = FALSE] explicitly selects the column dimension and prevents dropping it.

Step 3: Verify the selection. The extracted logical vector has four entries, matching the four records. The table form has four rows and one column named flagged. Both forms select the same records in the same order; only their structures differ.

Check. The field name stored in field was used to select flagged, not the literal column name typed into the indexing expression. A common mistake is to write claims$field and expect R to substitute the value of the object field. The dollar operator looks for a column named field; use claims[[field]] or claims[field] when the column name is stored in an object.

Choosing an Operator and Avoiding Traps

ExpressionTypical result for an ordinary atomic columnUseful when
df["x"]One-column data frameYou want a table, including when selecting one column
df[c("x", "y")]Data frame with the selected columnsYou want several columns and all rows
df[, "x", drop = FALSE]One-column data frameYou are using two-dimensional indexing and need to prevent dropping
df[["x"]]Extracted column componentYou need a column name that may be stored in an object
df$xExtracted column componentYou need a conveniently written, fixed column name

These descriptions of extracted results assume an ordinary atomic-vector column, such as the numeric, character, or logical columns in the examples. They do not guarantee that extraction always produces a vector. A data frame can also contain a list-valued or matrix-valued column; double brackets and the dollar operator return that component while preserving its underlying type. Check what type of result is appropriate for the data at hand instead of assuming every extracted column is a vector.

The dollar operator can also partially match a column name in some circumstances. For example, if a data frame has a column named payment, df$pay may match it even though pay is not the full name. Such code can become ambiguous or behave differently if similarly named columns are added. Prefer exact names where possible; for programmatic extraction, df[["payment", exact = TRUE]] requests an exact name match.

  • One bracket does not always mean a vector. df["x"] keeps a data frame; use double brackets or dollar extraction when you want the component.
  • A comma selection can drop a dimension. When selecting a single column with df[, "x"], include drop = FALSE if a data frame is required.
  • Names and positions are not interchangeable assumptions. A position refers to the column currently in that place; confirm the order before relying on it.
  • Dollar syntax does not substitute a name stored in an object. Use double brackets with the object that holds the name.
  • Extraction does not promise a vector. The result reflects the selected column’s underlying structure.
Key takeaway: Decide first whether the next step needs a table or a column component. Use single brackets to select columns as a data frame, add drop = FALSE when two-dimensional indexing must retain a one-column table, and use double brackets or dollar extraction when you need a column component. For a stored name, prefer exact double-bracket indexing.

Check Your Understanding

For each problem, identify the selection expression and the resulting form. Assume ordinary atomic-vector columns unless the question says otherwise.

  1. A hypothetical portfolio table has columns policy_id, region, and premium. Write an expression to select region and premium, in that order, for all rows, while retaining a data frame. (Answer: portfolio[c("region", "premium")]; a two-column data frame.)
  2. A data frame has a numeric amount column. You use records[, "amount"] and need a one-column data frame instead of a vector. What is the corrected expression? (Answer: records[, "amount", drop = FALSE].)
  3. A character object field_name contains the exact text "status". Write an expression that extracts the status component using that stored name. (Answer: records[[field_name, exact = TRUE]].)
  4. A data frame has 20 rows and an ordinary logical column called review. Compare the result forms of records["review"] and records[["review"]]. (Answer: the first is a 20-row, one-column data frame; the second is a logical vector of length 20.)
  5. A selected column is list-valued rather than an ordinary atomic vector. What should you expect from records[["details"]], and why should you avoid describing it automatically as a vector? (Answer: it returns the list-valued column as a list; extraction preserves the column’s underlying type, so it is not necessarily a vector.)
Clinical Biostats