str() is the data dictionary check
◈ 8 cardsstr(orders) prints 'data.frame': 12 obs. of 6 variables: then one line per column with its type — int, chr, int, chr. head(orders, 3) shows the first three rows; head() alone shows six. A $ amount : chr where int was expected means one cell in the column is not a number.
The first three calls after read.csv()
Module 2 built the data dictionary by hand: each variable, its type, its unit. str() — structure — prints R's version of it in one call, and it is the check that catches a broken import before any number is computed.
Worked example — str(orders)
> str(orders)
'data.frame': 12 obs. of 6 variables:
$ order_id : int 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 ...
$ prov : chr "ON" "QC" "ON" "BC" ...
$ channel : chr "Online" "Store" "Store" "Online" ...
$ amount : int 420 180 760 250 1320 510 90 640 305 980 ...
$ units : int 3 1 5 2 8 4 1 4 2 6 ...
$ order_date: chr "2025-01-06" "2025-01-08" "2025-01-15" "2025-01-21" ...
Read it top down. The first line is the shape: 12 observations of 6 variables — the same numbers dim() gave. Then one line per column: the name after $, the type, and the first few values. amount is int because every cell in the CSV was a whole number; a column with 420.50 in it would read num. Both are numeric and both add up. order_date is chr — text — which is why a monthly grouping in Module 12 starts with as.Date().
Compare this with the data dictionary you wrote: same variables, same types? Then the import is right.
head() and tail()
> head(orders, 3)
order_id prov channel amount units order_date
1 1001 ON Online 420 3 2025-01-06
2 1002 QC Store 180 1 2025-01-08
3 1003 ON Store 760 5 2025-01-15
head(orders) with no number shows six rows; tail(orders, 2) shows the last two, with their real row names (11 and 12). On a 10,000-row file these replace printing the frame.
The chr that should have been int
The February export arrives with one amount typed as 1,320 — a thousands separator. Read it and check:
> bad <- read.csv("orders_bad.csv")
> str(bad)
'data.frame': 12 obs. of 6 variables:
$ order_id : int 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 ...
$ prov : chr "ON" "QC" "ON" "BC" ...
$ channel : chr "Online" "Store" "Store" "Online" ...
$ amount : chr "420" "180" "760" "250" ...
$ units : int 3 1 5 2 8 4 1 4 2 6 ...
$ order_date: chr "2025-01-06" "2025-01-08" "2025-01-15" "2025-01-21" ...
> mean(bad$amount)
[1] NA
Warning message:
In mean.default(bad$amount) :
argument is not numeric or logical: returning NA
amount is now chr, with quotes around every value. One cell that is not a number turns the whole column into text — Module 9.4's coercion rule, arriving through a file. mean() returns NA with the warning you met there. The fix is Module 12's: repair the cell, as.numeric() the column, and check str() again. (A trailing space — "760 " — does not trigger this; read.csv() trims it. A comma, a $ sign or a stray letter does.)
Type the two calls, then read the structure
The worksheet reads two facts off str(orders); the questions cover the chr diagnosis, head()'s default, and what str() corresponds to in the process.
CRISP-DM: str() and head() are data understanding → describe data — and the chr check is the first verify data quality step.