Prepstellar

Data Analysis Fundamentals · Data Foundations and Loading

20 cards

Initial Data Inspection

Swipe, scroll or use ← →
  1. Preview the boundaries first

    The point of a first look is to learn what you are holding without paying to render all of it. A ten-million-row table printed in full tells you nothing you could not learn from twenty rows, and it costs you the notebook.

    Begin with a bounded preview rather than rendering an entire object. head() returns the first observations and tail() returns the last observations. Both methods display five elements by default, and each accepts a custom count.

    Call What you see
    head() The first five observations
    tail() The last five observations
    head(20) The first twenty observations
    tail(3) The last three observations
    1 / 20
  2. Preview the boundaries first

    The two boundaries hide different problems, which is why they are worth checking separately.

    The start of a file is where a stray header row, a units line, or a leftover comment tends to survive the import as if it were data. The end is where totals rows, footers and truncated final records show up. Neither shows in the other view.

    Use both views when the first and final records require inspection. On a very large import, head(n) and tail(n) with small explicit counts give you both boundaries for the price of a few rows — the output stays bounded no matter how big the table is.

    2 / 20
  3. Quick check

    A ten-million-row import may carry a malformed header near the start and a totals-like record at the end. Both boundaries must be inspected without rendering the whole table. What fits?

    1. ARender the full table once and scroll to each boundary in turn

      Rendering everything is exactly the cost the bounded preview exists to avoid, and it inspects nothing the preview cannot.

    2. BCall `describe()`, which returns both boundary records

      `describe()` returns a statistical summary; it does not show individual first or last records.

    3. CCall `head(n)` and `tail(n)` with small explicit counts

      Right. The two previews target the first and last observations, and an explicit count keeps the output bounded.

    3 / 20

  4. Summarize the numeric variables

    A preview shows you rows; a summary shows you distributions. Use describe() to compute a compact statistical summary for a Series or DataFrame columns, excluding missing values.

    For numeric data, the default summary includes count, mean, sample standard deviation, minimum, the twenty-fifth, fiftieth, and seventy-fifth percentiles, and maximum.

    Line What it tells you
    count How many nonmissing observations there are
    mean, std Center and spread, using the sample standard deviation
    min, max The extremes, where impossible values usually surface
    25%, 50%, 75% The quartiles, which expose skew and outliers

    The fiftieth percentile is the median, and the median is included even when a custom percentile list is supplied — so asking for your own percentiles adds to that output rather than replacing the center of it.

    4 / 20
  5. Quick check

    Which of these appears in the default numeric output of `describe()`?

    1. AThe complete list of the column's values in sorted order

      A summary is compact by design; it reports statistics about the values rather than reprinting them.

    2. BThe sample standard deviation of the column

      Right. The default numeric summary reports count, mean, sample standard deviation, minimum, the quartiles, and maximum.

    3. CThe memory that the column occupies in the table

      Memory use is not part of this statistical summary, which describes distributions rather than storage.

    5 / 20

  6. Summarize the nonnumeric variables

    A mean has no meaning for a status code or a country name, so the summary changes shape for these columns. For a nonnumeric Series, describe() reports the nonmissing count, number of unique values, most frequent value, and its frequency.

    Line What it tells you
    count Nonmissing observations
    unique How many distinct values exist
    top The most frequent value
    freq How often that value occurs

    This is a cardinality report, and it answers different questions: is this column a small set of categories or effectively an identifier? Is one value swallowing the whole column? Those are the failures worth catching early in text data, and no numeric moment would reveal them.

    6 / 20
  7. Quick check

    `describe()` is called on a Series of text status codes. What does the output report?

    1. ANonmissing count, number of unique values, top value and its frequency

      Right. The nonnumeric summary covers presence, cardinality, the most frequent value, and how often it occurs.

    2. BMean, variance, skewness and cumulative sum of the codes

      Numeric moments cannot be computed from text, and they are not what the nonnumeric summary reports.

    3. CRow labels, column labels, shape and memory footprint

      Those are structural attributes of the object rather than a statistical summary of its values.

    7 / 20

  8. Keep your progress in the app

    That’s 3 of 8 quick checks. In the app they stay answered, and every lesson remembers where you left off.

  9. Decide which columns the summary covers

    A mixed-type DataFrame needs an explicit scope decision, and the default is narrower than most people expect. By default, describe() on a mixed-type DataFrame restricts the result to numeric columns. Text columns are simply absent from the output — not empty, absent.

    Call Columns summarized
    describe() Numeric columns only
    describe(include=["number"]) Numeric columns
    describe(include=["object"]) Object columns
    describe(include="all") Both available families

    Passing include=["object"] requests object columns, include=["number"] requests numeric columns, and include="all" includes both available families. So a report that must cover numeric amounts and text statuses needs include="all"; the plain call silently leaves the statuses out.

    8 / 20
  10. Decide which columns the summary covers

    One more habit belongs to reading the output rather than requesting it. Descriptive aggregation methods generally skip missing data by default; setting skipna=False for methods that accept it changes that choice. Therefore, the count in a summary is evidence about nonmissing observations, not automatically the total row count.

    That distinction is a cheap and effective missing-data check:

    • If count matches the number of rows, the column has no missing values.
    • If it falls short, the gap is the count of missing values in that column.
    • Two columns with different counts have different amounts of missing data, whatever the row total says.

    Read that way, describe() does double duty: it characterizes the distribution and it quantifies what is absent.

    9 / 20
  11. Quick check

    A mixed table holds numeric amounts and text statuses. The report must summarize both families and state how many observations each figure rests on. Which approach is right?

    1. ACall `describe()` plainly and assume the text statuses appear alongside the amounts

      The plain call restricts a mixed table to its numeric columns, so the statuses would be missing from the report.

    2. BCall `head()` and treat the preview as the whole summary

      A preview shows a handful of rows; it is not a statistical summary and says nothing about the rest of the table.

    3. CCall `describe(include="all")` and read each count as nonmissing observations

      Right. The `all` scope covers both available families, and the count reports nonmissing observations rather than the row total.

    10 / 20

  12. Order by labels or by values

    Sorting makes the inspection order explicit, so that what you look at is a decision rather than an accident of how the file arrived. Two methods do it, and they sort different things.

    sort_index() sorts by index labels, and on a DataFrame axis=1 sorts column labels. sort_values() sorts a Series by its values or a DataFrame by values named in by.

    Goal Method
    Put rows in label order sort_index()
    Put columns in name order sort_index(axis=1)
    Order a Series by its values sort_values()
    Order a table by one or more columns sort_values(by=...)

    Both label and value sorting can be descending with ascending=False.

    11 / 20
  13. Order by labels or by values

    A list passed to by defines multiple sort keys in sequence. This is precedence, not a set: by=["team", "score"] orders by team first, and only settles ties inside a team by score. Reversing the list gives a genuinely different table.

    Choosing the wrong method is a common early mistake, because both produce an order and neither raises an error:

    • Sorting labels tells you nothing about which observations are largest.
    • Sorting values scrambles the label order you may have relied on for a previous comparison.

    Sorting also makes a run reproducible. Two people who sort the same table the same way see the same rows in the same places, which matters as soon as anomalies get reported by position.

    12 / 20
  14. Quick check

    A table must be ordered by `team`, with ties inside each team broken by `score`. Which call expresses that?

    1. A`sort_values(by=["team", "score"])`, keys taken in that order

      Right. A list passed to `by` sets the sort keys in sequence, so `score` only settles ties within a team.

    2. B`sort_index(axis=1)`, which orders the labels of both axes at once

      That call sorts column labels; it does not order observations by the values in any column.

    3. C`sort_values(by="score")` followed by renaming the index to team

      Sorting by score alone loses the grouping by team, and renaming labels does not reorder anything.

    13 / 20

  15. Decide where missing values go

    Missing-value placement is a separate decision, and leaving it implicit is how missing rows go unnoticed at the bottom of an output. sort_values() places missing values last by default and accepts na_position="first" to place them first.

    Setting Where the missing rows land
    Default After all nonmissing values
    na_position="first" Before all nonmissing values

    Both choices are defensible; what matters is that you make one. If the purpose of the sort is to find incomplete records, put them first, where a bounded head() will show them. If the purpose is to read the extremes of a distribution, leaving them last keeps them out of the way. Note that the rows are always in the result either way — sorting places missing values, it never removes them.

    14 / 20
  16. Quick check

    `sort_values()` is called on a column that contains missing values, with no further arguments. Where do the missing rows appear?

    1. AThey keep the position they had before the sort

      Every row takes its place in the new order; missing values are positioned rather than left untouched.

    2. BThey are moved after all of the nonmissing values

      Right. Missing values are placed last by default, and `na_position="first"` moves them to the front instead.

    3. CThey come back separate from the sorted result

      One sorted object comes back; the missing rows sit inside it rather than in a second result.

    15 / 20

  17. Compare on transformed values with a key

    Sometimes the order you want is not the order the raw values give. Team, team and TEAM sort into three separate groups if the comparison is literal, which is rarely what a reviewer means.

    Sorting also accepts a key callable that transforms the values used for comparison while leaving the returned values in their original representation. A string-lowering key can provide case-insensitive ordering: the comparison sees lowercase text, and the sorted output still shows the names as they were stored.

    16 / 20
  18. Compare on transformed values with a key

    The contract is what keeps this safe. On a DataFrame, that key is applied to each sort column separately and must return an equally shaped Series or array.

    • It receives one column at a time, so it does not need to know about the other sort keys.
    • It must return one comparison value per input value — same shape in, same shape out.
    • Returning a scalar, a differently sized list, or an extra column breaks the one-to-one pairing the sort depends on.

    Put the three tools together and an inspection pass is complete: preview both boundaries, summarize the dtype families you actually care about, and order by the labels or values that make anomalies and later operations reproducible. A review that must order by team then score, compare names without case sensitivity, and surface incomplete records first is a single call with by, key and na_position="first" set together.

    17 / 20
  19. Quick check

    A `key` callable is supplied to sort a DataFrame case-insensitively by two text columns. What must the callable return?

    1. AA single scalar holding the value that should sort first

      A single scalar cannot order a column, since the sort needs one comparison value per value.

    2. BA Series or array shaped exactly like the column it received

      Right. The key runs on each sort column separately and must return an equally shaped Series or array.

    3. CA DataFrame carrying an extra column of comparison values for the sort

      The key supplies comparison values for the column it is given; it does not add columns to the table.

    18 / 20

  20. Key takeaways

    • Use head() and tail() for bounded first-and-last previews — five elements by default, any count you ask for, and both boundaries when a file may be damaged at either end.
    • Read describe() for what it is: count, mean, sample standard deviation, minimum, quartiles and maximum for numeric data, and count, unique, top and frequency for nonnumeric data, with missing values excluded.
    • Choose the dtype families included in describe() when a DataFrame is mixed — the default is numeric only, and include="all" covers both available families.
    • Distinguish sorting labels with sort_index() from sorting observations by values with sort_values(), where a list in by sets the key order and ascending=False reverses either kind of sort.
    • Set missing-value placement explicitly when it matters to inspection: last by default, first with na_position="first", and use a key callable when the comparison should run on transformed values.
    19 / 20
  21. Quick check

    Which statement describes these inspection tools correctly?

    1. A`describe()` covers every column of a mixed table, and `tail()` summarizes distributions

      A mixed table defaults to numeric columns only, and `tail()` previews final rows rather than summarizing them.

    2. B`sort_index()` orders rows by their values, and missing values are dropped from the result

      `sort_index()` orders by labels, and missing values are placed within the result rather than removed.

    3. C`sort_values()` orders rows by column values, and counts exclude missing data

      Right. Value sorting works from the named columns, and each count in a summary reports nonmissing observations.

    20 / 20

  22. 8 quick checks · then the test

    In the app, finishing the quick checks opens this lesson’s 10-question test, and the ones you miss come back exactly when you’re about to forget them.

The whole course, on your phone

Lessons you can read, audio you can listen to on the way to work, and practice that remembers what you got wrong.