Loading and Storing Data in pandas: CSV, Excel, JSON and SQL

Learn to bring data into pandas from the formats analysts meet every day, and to save it again without losing information. Read CSV and other text files with the right delimiters, number formats, missing-value markers, dates and encodings, including reports with title lines and footers. Load Excel workbooks, JSON files and web APIs, store results as CSV, Excel and Parquet, and read from and write to SQL databases with safe, parameterized queries.

IntermediateLesson 3 of 8 in Data Analysis with Python Course

What you will learn

  1. Read CSV and other delimited text files with pd.read_csv, control how pandas splits, labels and types the columns, and check the result before you analyze it.
    • Read a CSV file and inspect what pandas created
      Load a comma-separated file into a DataFrame, choose the header, column names, index and columns to keep, and check the types pandas inferred.
    • Handle delimiters and regional number formats
      Recognize the delimiter, decimal mark and thousands separator a file uses, and set sep, decimal and thousands so that numbers load as numbers.
    • Control missing values, column types and dates while reading
      Tell pandas which markers mean "missing", keep identifiers as text, choose numeric types and parse dates with an explicit format.
    • Read files with messy layouts
      Skip title lines, comments and footers, read multi-row headers and fixed-width columns, and decide what to do with malformed lines.
  2. Understand how text is stored as bytes, fix encoding errors and garbled characters, and read files that are too large or too slow to load in one piece.
    • Understand how characters become bytes
      Explain what an encoding is and recognize ASCII, UTF-8, Latin-1, Windows-1252, UTF-16 and the byte order mark.
    • Diagnose and fix encoding problems
      Recognize a decoding error and mojibake, find the right encoding, and write files that other programs read correctly.
    • Read large and compressed text files efficiently
      Reduce memory use while reading, process a file in chunks, combine partial results correctly and read compressed files directly.
  3. Read data from worksheets with titles, merged cells and formulas, and write one or more DataFrames to a workbook for other people.
    • Read worksheets from Excel workbooks
      Choose the sheet, rows and columns to read, and know what pandas does with dates, formulas, merged cells and formatting.
    • Write DataFrames to Excel workbooks
      Save one or several tables to a workbook that colleagues can open, and avoid overwriting or mislabeling data.
  4. Read and write JSON, turn nested records into tables, and request data from web APIs reliably and safely.
    • Read and write JSON data
      Know JSON's syntax and its mapping to Python objects, and read and write JSON and JSON Lines with Python and pandas.
    • Flatten nested JSON into a table
      Turn nested objects and lists into columns and rows with pd.json_normalize, and decide what one row represents.
    • Request data from a web API
      Call an API with the requests library, check the response, handle keys, pages and rate limits, and read tables from web pages.
  5. Write clean results to CSV, compare text and binary formats, and use Parquet to keep data compact and correctly typed between analysis steps.
    • Write DataFrames to CSV and text files
      Control the index, missing values, number and date formats and encoding of written files, and keep raw data safe.
    • Compare text and binary storage formats
      Explain how text, row-based and columnar binary formats differ, and choose CSV, Excel, JSON, Parquet, Feather, pickle or a database for a given job.
    • Read and write Parquet files
      Save DataFrames to Parquet with their types, read selected columns, and organize data as a partitioned dataset.
  6. Connect pandas to a database, load query results with parameters and correct types, and write DataFrames to tables safely.
    • Connect to a database and load query results
      Open a connection to SQLite or another database, run a given SQL query from pandas and manage credentials and connections.
    • Pass query parameters safely and control result types
      Insert values into queries with parameters instead of string formatting, and get correct dates, integers and chunk sizes in the result.
    • Write DataFrames to database tables
      Create, append to and replace tables with to_sql, choose column types, and verify and repeat writes safely.

Loading and Storing Data in pandas study guide

6 chapters

1

Load delimited text files into pandas

Text files can look like tables while leaving important choices unstated. You will read records into pandas, check the resulting rows and columns, and choose options for headers, quoted fields, number conventions, missing markers and dates. You will also locate the actual observations inside reports that contain titles, comments and totals, so a completed import gives you the intended table and values.

1.1 From CSV records to a checked table

A CSV file is plain text organized into records and fields. Commas usually separate fields, and the first record often supplies column names. The file contains characters, not a pandas schema, so reading it also means deciding what those characters represent.

Load and inspect a small file

Suppose a file contains:

order_id,date,region,units,price
1001,2026-03-02,North,3,4.50
1002,2026-03-02,South,1,12.00
1003,2026-03-03,North,2,7.25

Read it and inspect the result:

import pandas as pd

df = pd.read_csv("sales.csv")
print(df.head())
print(df.shape)
print(df.dtypes)
df.info()

The shape is (3, 5): three data rows and five columns. pandas infers int64 for order_id and units, and float64 for price. The date column still contains text. In pandas 3, inferred text columns normally show str; older pandas versions often show object.

Each inspection answers a different question. head() shows whether fields line up with their labels. shape exposes missing rows or an unexpected extra column. dtypes checks interpretation, and info() adds non-null counts. A column intended for numbers that loads as text deserves a look at the raw values: a unit, a placeholder or a different decimal convention can stop numeric inference.

Match labels to records

For a headerless file whose first line is 1001,North,3, use:

df = pd.read_csv(
    "orders.txt",
    header=None,
    names=["id", "region", "units"]
)

Without that choice, pandas takes the first record as the header. Its values become column names and the record disappears from the data. Use index_col="order_id" when an existing column should label rows. Use usecols=["region", "units"] to read just those columns, or nrows=1000 to inspect the first 1,000 data rows before loading a large file.

Let the CSV reader handle quotes

The record "Smith, Jane",Boston,10 has three fields. The comma inside the quoted name belongs to that name. Two double quotes inside a quoted field represent one literal double quote: "O'Neil ""Red""" becomes O'Neil "Red". A quoted field can even contain a line break, so records and physical lines do not always match.

Calling line.split(",") cuts the name apart and cannot handle these rules. read_csv handles them as part of parsing. pd.read_table uses tab as its default separator; pd.read_fwf handles fields defined by character positions.

Find the file Python is looking for

A relative path is resolved from the program's current working directory. If "data/sales.csv" cannot be found, inspect it with Path.cwd() after from pathlib import Path. An absolute path, a Path object, a URL or an in-memory text file such as StringIO can also be passed to read_csv. Check the location before changing parsing options: a missing file and a badly parsed file are different problems.

Key Takeaways

  • CSV stores characters; pandas infers the column types when reading.
  • Check the first rows, shape, types and non-null counts after an import.
  • Use header=None and names when the file has no header.
  • Quoted delimiters and line breaks belong inside fields; use a CSV parser.
  • Relative paths start from the current working directory.

1.2 Separators and numbers that load correctly

A delimiter separates fields; a decimal mark separates the whole and fractional parts of a number. A thousands separator groups digits. These three jobs need separate settings, even when the same symbol is used for different jobs in different files.

Inspect characters before choosing options

Look at a few raw lines in an editor. A .csv extension does not guarantee commas, and .txt does not identify a layout. Common settings are:

File layoutReading option
Tab-separated fieldssep="\t"
Pipe-separated fields`sep="
Fields separated by runs of spacessep=r"\s+"
Semicolon-separated fieldssep=";"

You can inspect the beginning without reading the whole file:

with open("products.csv", encoding="utf-8") as f:
    print(f.readline())
    print(f.readline())
Work through a regional export

Consider this text:

product;price;qty
Tea;3,50;1.200
Coffee;12,90;850

The semicolons divide fields, the comma is the decimal mark, and the point groups thousands. Read all three conventions explicitly:

df = pd.read_csv(
    "products.csv",
    sep=";",
    decimal=",",
    thousands="."
)

The prices become 3.5 and 12.9. The quantities become 1200 and 850. With the default comma separator, this header does not describe three comma-separated columns. Even after choosing sep=";", the job is unfinished: the prices remain text and "1.200" can become the decimal 1.2. That last result is a valid number with the wrong meaning, so no parsing exception is needed for a serious error.

Compare a few loaded values with their source text and inspect describe() for implausible ranges. A quantity expected in the thousands that appears near one points toward a number-convention problem. Changing the delimiter alone will not repair it.

Keep field boundaries separate from number grouping

In a comma-delimited file, a grouped number such as "1,234.50" must be quoted. Its internal comma is part of the number. With thousands=",", pandas can read the quoted field as 1234.5. Without quotes, the comma also creates a field boundary; thousands cannot restore the lost record structure.

Choose a compatible parsing engine

The default C engine handles common layouts quickly. The Python engine supports separator detection with sep=None, regular-expression separators and skipfooter. Detection examines a sample and can choose badly on an irregular report, so state a known separator directly.

A separator longer than one character is generally treated as a regular expression and requires the Python engine; r"\s+" is a special case also supported by the C engine. The PyArrow engine can read with parallel threads, but supports a different set of options. For example, chunksize is unsupported with engine="pyarrow". Choose the engine for the options your file needs, then check the result's structure and values.

Key Takeaways

  • Choose sep, decimal and thousands for their separate jobs.
  • A numeric-looking result can still be wrong by a factor of 1,000.
  • Quote a field when its content includes the delimiter.
  • The Python engine supports detection and skipfooter; engine options differ.

1.3 Missing values, identifiers and dates

Type inference cannot know whether 999 is a measurement or a code for an unknown value. It also cannot know whether leading zeros carry meaning. Use the data's definitions to set reading options before inference changes those values.

Declare missing markers where they apply

pandas recognizes empty fields and built-in markers such as "NA", "N/A", "n/a", "NULL", "NaN" and "None". A source can use additional markers. Suppose score contains 88, "n/a", "-" and 999, with 999 defined as unknown:

df = pd.read_csv(
    "scores.csv",
    na_values={"score": ["-", "999"]}
)

The score column now contains 88.0 and three missing values. Without declaring the markers, "-" can keep the column as text; an undeclared numeric sentinel can enter calculations. The mean of 88 and 999 is 543.5, although the only known score is 88.

A dictionary confines a marker to its column. A file-wide na_values=["999"] would also remove a real product code 999. If "NA" is a real label, use keep_default_na=False to turn off the built-in marker list and explicitly list the markers that do mean missing. With that setting, include "" if empty fields must still count as missing.

Preserve values according to their role

Read identifiers as text:

df = pd.read_csv(
    "visits.csv",
    dtype={"site_code": str, "visits": "Int64"}
)

A code such as "00501" must stay five characters long. Reading it as an integer gives 501; converting that integer to text later produces "501", not the original code. Use a numeric type for values you calculate with.

Ordinary NumPy integer columns cannot hold NaN, so a count column with a gap often becomes float64. pandas's nullable "Int64", with a capital I, keeps integer values and represents a gap with <NA>. dtype_backend="numpy_nullable" requests nullable types across the result. For a small repeated set of labels, dtype={"region": "category"} stores the labels as categories and can reduce memory use.

Specify how dates are written

Date-looking text remains text until parsed. For day-first dates such as "03/04/2026" and "13/04/2026", use:

df = pd.read_csv(
    "events.csv",
    parse_dates=["day"],
    date_format="%d/%m/%Y"
)

These values become April 3 and April 13. Without a format, a month-first guess can either swap valid days and months or fail to convert the column. dayfirst=True expresses a preference; an explicit format states the expected structure. ISO dates such as "2026-04-03" avoid day/month ambiguity.

After reading, inspect dtypes, isna().sum() and the row count. Check a date whose interpretation distinguishes the conventions. A column still showing text means parsing did not produce the intended datetime values; a missing count that rises unexpectedly can reveal a real label mistaken for a marker.

Key Takeaways

  • Declare source-specific missing markers, preferably per column.
  • Use keep_default_na=False when a built-in marker is real data.
  • Read digit-only identifiers as text to preserve leading zeros.
  • Use nullable Int64 for integer counts with missing values.
  • Give ambiguous dates an explicit format and verify their dtype.
  • Check missing-value counts against the source.

1.4 Tables inside reports and fixed-width files

A report can mix a table with titles, blank lines, comments, totals and source notes. First locate the header and the data boundaries. Otherwise a reader can mistake a title for column names or include a total as an ordinary observation.

Read only the table

A report contains these nine physical lines:

Monthly sales report
Exported 2026-04-01

region,jan,feb
North,120,135
# test row below
South,98,101
Total,218,236
Source: internal system

The first three lines precede the header. The last two are not observations. Read it with:

df = pd.read_csv(
    "report.csv",
    skiprows=3,
    comment="#",
    skipfooter=2,
    engine="python"
)

The result has two rows. January totals 218 from North and South. Keeping the total row would add another 218 and report 436. With the defaults, the one-field title can instead become the header and lead to a parsing error when three-field records arrive.

skiprows=3 counts the first three physical lines, including the blank line. A list such as skiprows=[0, 2] removes particular zero-based line positions. Blank lines are skipped by default, and comment="#" removes comment text. skipfooter needs the Python engine. Match these settings to the actual layout; a fixed skip count can stop being correct when an exporter adds a title line.

Investigate malformed records

A record with too many fields can trigger on_bad_lines="error", the default. "warn" skips it with a warning, while "skip" drops it silently. Before choosing either, inspect the raw record. An unquoted comma inside a name or a wrong delimiter can create extra fields; skipping then loses a valid observation instead of repairing the cause.

Too few fields behave differently. Under id,name,score, the record 2,Ben loads with a missing score. It need not raise an error. Check missing counts as well as row counts, and compare the kept records with the source when excluding malformed lines.

Read stacked headers or character positions

Two rows of column labels can form a MultiIndex. With group labels region,sales,sales above ,2025,2026, header=[0, 1] produces labels such as ("sales", "2025"). If flat labels suit the analysis better, skip both header rows and supply names=["region", "sales_2025", "sales_2026"].

Fixed-width text has no delimiter. Column boundaries are character positions:

df = pd.read_fwf(
    "readings.txt",
    colspecs=[(0, 4), (4, 11), (11, 16)]
)

These half-open ranges include each start and exclude its end. The first field occupies positions 0 through 3, and the next starts at 4. widths=[4, 7, 5] describes the same layout. Inference is convenient for regular samples; explicit boundaries prevent a short early value from defining the wrong width.

Key Takeaways

  • Locate the header, observations and footer before choosing skip options.
  • Total rows included as observations can double a sum.
  • Skipping bad lines loses records; investigate extra fields first.
  • Short records can load with trailing missing values.
  • Use multi-row headers or explicit fixed-width boundaries for those layouts.
2

Read text correctly and efficiently

Correct text depends on the rule used to decode its bytes, and efficient reading depends on what the program keeps in memory. You will distinguish encoding failures from garbled text, use evidence to select an encoding, and preserve characters during exchange. Then you will reduce large-file memory use through column selection, suitable types and chunked processing, including how to combine partial results correctly.

2.1 How text is stored as bytes

A file stores bytes, each with a value from 0 to 255. An encoding defines how characters are represented by those bytes. Encoding converts Python text to bytes; decoding converts bytes back to text. The same bytes can mean different characters under different decoding rules.

Count characters and bytes separately
text = "café"
raw = text.encode("utf-8")
print(len(text))  # 4 characters
print(len(raw))   # 5 bytes
print(raw.decode("utf-8"))  # café

The accent does not make a second visible character here. The letter "é" needs two bytes in UTF-8, so four characters occupy five bytes. A byte count and a character count answer different questions.

ASCII defines 128 characters, including basic English letters, digits, punctuation and control codes. Their byte values agree across ASCII, UTF-8, Latin-1 and Windows-1252. That shared beginning explains why an English-only sample can look correct even when the encoding setting is wrong.

Recognize the main encoding families
EncodingHow it represents textUseful clue
UTF-8One to four bytes per Unicode characterASCII letters use one byte; "é" uses two
Latin-1One byte per character in its limited repertoireEvery byte value decodes
Windows-1252One byte per supported characterIncludes extra printable symbols such as "€"
UTF-16Usually two bytes per character, four for othersByte order matters

UTF-8 represents every Unicode character and is the usual choice for exchanged text. Latin-1 and Windows-1252 represent a smaller set of characters. They agree on many accented letters but differ in part of the byte range: Windows-1252 uses byte 0x80 for "€", where Latin-1 has a control character. They are not interchangeable names for one encoding.

Read byte order marks correctly

A byte order mark, or BOM, is a marker at the start of some files. UTF-16 can begin with FF FE for little-endian order or FE FF for big-endian order. encoding="utf-16" uses the BOM to select the order. Without a BOM, specify "utf-16-le" or "utf-16-be" according to the source.

A UTF-8 BOM is EF BB BF. Python's open(..., encoding="utf-8-sig") removes it while decoding. Plain "utf-8" in open() retains it as \ufeff, which can unexpectedly become part of the first header name. pandas's CSV reader also handles a leading UTF-8 BOM, but choosing utf-8-sig makes the intended file convention clear.

Make the encoding explicit
with open("notes.txt", encoding="utf-8") as f:
    text = f.read()

The default of open() depends on Python's version and UTF-8 mode. Python 3.11–3.14 can use the locale's encoding; Python 3.15 enables UTF-8 mode by default, with an opt-out. An explicit encoding keeps the script tied to the file's actual format across computers. It also prevents a platform default from silently changing how the same bytes are read.

Key Takeaways

  • Encoding turns text into bytes; decoding turns bytes into text.
  • Character counts and byte counts can differ.
  • ASCII-only samples can hide an incorrect encoding choice.
  • Latin-1 and Windows-1252 differ despite sharing many characters.
  • Use BOM and byte-order information when reading UTF-16.
  • Pass the intended encoding explicitly to open().

2.2 Find the cause of garbled text

A wrong encoding can fail loudly with UnicodeDecodeError, or quietly produce readable-looking nonsense called mojibake. Both problems start with interpreting bytes under the wrong rule. Keep the original file so you can decode it again.

Diagnose an error from the source

A CSV saved as Windows-1252 contains city names including "Zürich" and "Málaga". Reading it as UTF-8 can fail at byte 0xfc, used for "ü" in Windows-1252. Once the source's export settings confirm its encoding, read it with:

df = pd.read_csv("cities.csv", encoding="cp1252")
print(df["city"].head())

Inspect names containing accents or symbols. A sample made entirely of ASCII characters cannot distinguish these encodings. A particular invalid UTF-8 byte suggests a possible legacy encoding; it does not uniquely identify which legacy encoding produced the file.

Recognize an error that did not raise

UTF-8 bytes decoded as Windows-1252 can turn "café" into "café" and "São Paulo" into "São Paulo". The reader has produced characters successfully, but they are the wrong characters. Read the original bytes again using UTF-8:

df = pd.read_csv("cities.csv", encoding="utf-8")

Search-and-replace repairs one visible symptom at a time and can miss other damaged letters. It also risks changing a genuine occurrence of a character. Correct decoding addresses the cause for the whole file.

Gather evidence for the encoding

Start with the supplier's documentation or export settings. Inspect a small byte sample if needed:

with open("cities.csv", "rb") as f:
    sample = f.read(200)
print(sample)

Binary mode preserves the bytes without decoding. A BOM can give a direct clue. A detector such as charset-normalizer estimates a likely encoding, but a short sample may fit several candidates. Test the result against known accented names and symbols.

Latin-1 assigns a character to every byte, so it can decode any byte sequence without an error. That success alone says nothing about whether the characters are right. Windows-1252 also uses single-byte characters but leaves a few byte values undefined and can raise a decoding error.

Avoid discarding the evidence

encoding_errors="replace" substitutes "�" for bytes the decoder cannot read. encoding_errors="ignore" drops them. These options can help inspect damaged input, but they lose information and should not stand in for finding the correct encoding. A name changed to "Zrich" can break a match as surely as visibly garbled text.

For output, UTF-8 handles the widest range of characters. Some spreadsheet programs identify it more reliably when a BOM is present:

df.to_csv("cities_export.csv", index=False, encoding="utf-8-sig")

Reopen the export in the receiving program and inspect the same accented values. The goal is the correct text at both ends of the exchange.

Key Takeaways

  • Check both decoding errors and visibly garbled characters.
  • Read original bytes again with the correct encoding to repair mojibake.
  • Latin-1 decoding success does not establish that the text is correct.
  • Replacement and ignore modes discard character information.
  • Use UTF-8 with a BOM when the receiving spreadsheet program needs it.

2.3 Read large files without keeping every row

The file's size on disk is not its memory requirement. pandas builds arrays, indexes and text values in memory, and their types affect the space needed. Measure with df.memory_usage(deep=True) or df.info(memory_usage="deep") before deciding how to load more data.

Reduce the data you bring into memory

Read selected columns with usecols, inspect an initial sample with nrows, and choose suitable types with dtype. A category can store repeated region names compactly. float32 uses less space than float64, but offers about seven significant digits, so choose it only when that precision fits the measurements. A small preview helps identify types; it does not establish that every later row follows the same pattern.

Process chunks and keep a small result

chunksize changes the return value from a DataFrame to an iterator of DataFrames. For a total and a mean:

total = 0.0
count = 0
with pd.read_csv(
    "measurements.csv",
    usecols=["amount"],
    chunksize=100_000
) as reader:
    for chunk in reader:
        total += chunk["amount"].sum()
        count += chunk["amount"].count()
mean = total / count if count else float("nan")

The loop keeps a running sum and count of nonmissing values. Each chunk can be released after use. Collecting all chunks in a list and concatenating them later recreates the full memory requirement; chunking saves memory only when the work keeps a reduced result or writes processed pieces out.

A ten-row file read with chunksize=4 gives pieces of 4, 4 and 2 rows. For amounts 1 through 10 with regions cycling N, S, E, add partial regional totals to obtain N 22, S 15 and E 18. Their combined total is 55.

Combine the right quantities

Sums and counts add. Minimums combine by taking the smallest partial minimum; maximums combine by taking the largest partial maximum. Means need weights because chunks can contain different numbers of valid observations.

For values 1, 2 and 3 in one chunk and 10 in another, the chunk means are 2 and 10. Averaging those means gives 6, treating the one-value chunk as equal in weight to the three-value chunk. Add the sums and counts instead: total 16 across four observations gives mean 4. Chunk medians do not contain enough information to reconstruct an overall median.

Read compressed files directly

read_csv normally infers compression from recognized extensions such as .gz, .bz2, .zip, .xz and .zst. It decompresses while reading:

with pd.read_csv("measurements.csv.gz", chunksize=100_000) as reader:
    for chunk in reader:
        print(len(chunk))

A ZIP archive used this way must contain exactly one data file. df.to_csv("out.csv.gz", index=False) writes gzip-compressed CSV. Compression reduces disk space and transfer size; it does not remove the memory used by the decoded table. For repeated analysis, converting a checked dataset to Parquet also avoids reparsing text and restores its stored column types.

Key Takeaways

  • Measure deep memory use and read only needed columns.
  • Chunked readers yield DataFrames; keep reduced results to save memory.
  • Combine sums and nonmissing counts before calculating an overall mean.
  • Chunk medians cannot be combined into the overall median.
  • Compressed text is decompressed during reading; a ZIP needs one data file.
  • Parquet suits datasets that are loaded repeatedly.
3

Work with Excel workbooks

Workbooks mix data with a presentation built for people: several sheets, titles, formulas, merged labels and display formats. You will locate a table within that layout and distinguish stored values from what a cell displays. You will then write single-sheet and multi-sheet reports, control updates to an existing workbook and check that the saved sheets contain the intended rows and values.

3.1 Find and read the table on a worksheet

An Excel workbook can contain several sheets, titles and calculated totals. Cells have stored values and types as well as display formatting. Reading a worksheet means locating the data table and understanding which parts of the workbook become DataFrame values.

Choose the sheet and its boundaries
df = pd.read_excel(
    "quarterly.xlsx",
    sheet_name="Q1",
    skiprows=2,
    usecols="A:C",
    nrows=2
)

Suppose row 1 is a merged title, row 2 is blank, row 3 holds region, date and sales, and rows 4–5 hold the observations. skiprows=2 makes row 3 the header; nrows=2 stops before the total in row 6. For North 1200 and South 950, the two observations sum to 2150. Including a cached total of 2150 as a third observation would double that amount.

Excel displays row numbers starting at 1; pandas row positions start at 0. header=2 also selects Excel row 3 as the header. usecols="A,C,E:F" selects separate columns and a range. The default sheet_name=0 reads the first sheet; a name selects a specific sheet, and sheet_name=1 selects the second.

sheet_name=None returns a dictionary of sheet names to DataFrames. Select a key or loop over .items(); the dictionary itself is not one DataFrame. For several reads from one workbook:

with pd.ExcelFile("quarterly.xlsx") as xf:
    print(xf.sheet_names)
    q1 = pd.read_excel(xf, sheet_name="Q1")
Know what the cell really stores

A percentage displayed as "15%" stores 0.15. A number displayed with five digits may store 2139, even though the screen shows "02139". No reading option can recover a zero that exists only in formatting. Store identifiers as text in the workbook and also pass dtype={"zip": str} when reading; pandas can otherwise infer integers even from digit-only text cells.

Excel numeric precision is limited to 15 significant digits. A 16-digit identifier entered as a number can already be damaged before Python reads it. Store such values as text. A worksheet has at most 1,048,576 rows and 16,384 columns, so a very large dataset needs another format.

Treat formulas and merged cells carefully

pandas does not calculate formulas. It reads cached results stored in the workbook. A spreadsheet application can save current results; a script-generated file may have missing, placeholder or stale caches. openpyxl does not calculate a result, and XlsxWriter normally writes a zero placeholder unless given one. Recalculate important values in pandas or open and save the workbook in a spreadsheet program before relying on its cached totals.

Only the top-left cell of a merged range stores its label. A merged country label can therefore leave blanks in the rows below. When the layout confirms that the label applies to those rows, df["country"] = df["country"].ffill() carries it down. Inspect the table boundary before filling.

Reading requires an engine library. openpyxl handles .xlsx and .xlsm; xlrd handles .xls, pyxlsb handles .xlsb, odf handles .ods, and calamine supports several spreadsheet formats. A missing engine raises an ImportError naming the dependency. Colors, comments and other layout styling are not loaded as DataFrame data.

Key Takeaways

  • Select the sheet, header, columns and observation rows explicitly.
  • sheet_name=None returns a dictionary of DataFrames.
  • Stored values can differ from displayed percentages or padded identifiers.
  • Formulas are not calculated by pandas; their caches can be stale or missing.
  • Merged labels reside in the top-left cell.
  • Store long identifiers as text before Excel can round them.
  • Install a reading engine compatible with the workbook format.

3.2 Write one workbook with several sheets

Excel is useful when people need to open and inspect a report in a spreadsheet program. A DataFrame can become one worksheet, or several DataFrames can share a workbook. Choose the destination path and sheet names before writing so each table goes to the intended place.

Write one table or several
weather.to_excel(
    "weather.xlsx",
    sheet_name="Weather",
    index=False
)

index=False keeps the default row numbers out of the worksheet. Without it, they appear as an extra first column and can come back as "Unnamed: 0" on a later read. Keep an index only when it contains meaningful labels that belong in the report.

A path-based to_excel call writes a workbook at that path, replacing an existing file. Calling it once for Weather and again for Counts at the same path can leave only the second table. Use one writer for both:

with pd.ExcelWriter("report.xlsx") as writer:
    weather.to_excel(writer, sheet_name="Weather", index=False)
    counts.to_excel(writer, sheet_name="Counts", index=False)

The context manager closes and finishes the workbook when the block ends. Reading it with pd.read_excel("report.xlsx", sheet_name=None) returns a dictionary containing both sheet names. Writing .xlsx requires openpyxl or XlsxWriter.

Update a sheet in an existing workbook

To preserve other sheets while replacing one, use an append-mode writer:

with pd.ExcelWriter(
    "report.xlsx",
    mode="a",
    engine="openpyxl",
    if_sheet_exists="replace"
) as writer:
    counts.to_excel(writer, sheet_name="Counts", index=False)

if_sheet_exists controls a name collision. "error" stops, "new" creates another sheet, "replace" replaces that sheet, and "overlay" writes into its existing cells. Overlay does not clear old cells outside the new table, so a shorter update can leave old rows behind. Decide whether the report needs a complete replacement of the sheet or a carefully positioned overlay.

Make the output easy to reopen

Sheet names have a 31-character limit and cannot contain :, \, /, ?, *, [ or ]. A short name such as "Q1 Summary" works; "Q1/Q2" contains a forbidden slash. Some engines warn instead of stopping for an overlong name, so choose compatible names yourself.

startrow and startcol position a table using zero-based offsets. na_rep gives missing values a visible marker. float_format="%.2f" rounds written numbers, and autofilter=True adds header filter buttons in pandas 3. Datetime columns are written as Excel dates.

Rounding on output changes stored numbers, not just their display. Keep a full-precision analysis file separately when a rounded report is needed. Reopen the workbook and check the sheet list, table dimensions and representative values. Excel reading is relatively slow and a round trip can change pandas dtypes, so use Parquet for intermediate analysis tables when type preservation matters.

Key Takeaways

  • Use one ExcelWriter to place several tables in a new workbook.
  • A path-based write replaces an existing workbook.
  • Append mode and if_sheet_exists control updates to existing sheets.
  • Choose valid sheet names and verify the reopened workbook.
4

Get data from JSON files and web APIs

JSON and web APIs bring records in shapes that do not always match a table. You will parse and write JSON, choose an appropriate table layout, and flatten nested objects or lists while keeping track of what each row represents. You will also check HTTP responses, continue through pages and handle credentials and rate limits, so the resulting dataset contains the records you intended to collect.

4.1 JSON objects, tables and line-by-line records

JSON stores nested data as text. Objects hold name-value pairs, arrays hold ordered values, and strings use double quotes. Its other values are numbers, true, false and null. Python's json module converts this syntax to Python objects before you build a table.

Parse and write valid JSON
import json

text = '{"station":"Oslo","active":true,"temp_c":[3.5,null,4.0]}'
data = json.loads(text)
print(data["active"])   # True
print(data["temp_c"])   # [3.5, None, 4.0]

Objects become dictionaries, arrays become lists, and null becomes None. json.loads parses a string; json.load reads an open file. The writing functions reverse that direction: json.dumps returns text and json.dump writes to a file.

with open("station.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

ensure_ascii=False leaves characters such as "ü" readable. The default can write the same character as \u00fc; both forms represent the same string. A printed Python dictionary is not JSON: single quotes, True, None and trailing commas are invalid JSON syntax. Standard JSON also has no NaN. Python's encoder permits it by default, but allow_nan=False rejects it; pandas writes missing values as null.

Match the table's layout

A JSON table needs an orientation, the arrangement of rows, labels and values. orient="records" gives one object per row:

[{"city":"Lyon","temp_c":21.5},{"city":"Osaka","temp_c":null}]

The default DataFrame orientation, "columns", groups values under column names and then row labels. "split" stores columns, index and data separately. Specify an orientation that matches the receiving program instead of assuming every JSON table has the same shape.

from io import StringIO
import pandas as pd

df = pd.read_json(
    StringIO('[{"code":"0042","amount":9.5}]'),
    orient="records",
    dtype={"code": str}
)

In pandas 3, a plain string passed to read_json is a path, so wrap actual JSON text in StringIO. Even JSON strings containing only digits can be inferred as numbers; the explicit dtype preserves "0042".

Use JSON Lines for sequential records

JSON Lines has one complete JSON object per line, without an enclosing array or commas between records:

{"id":1,"amount":9.5}
{"id":2,"amount":12.0}

Read it with pd.read_json(path, lines=True) and write it with df.to_json(path, orient="records", lines=True). The reader's chunksize and nrows options require lines=True, which makes individual records available sequentially.

When exporting dates, set date_format="iso" for readable ISO timestamps. pandas 3.1 still defaults to epoch milliseconds for ordinary DataFrame JSON output, but that default is changing. Explicit date output avoids relying on a reader to guess what a large integer represents.

Key Takeaways

  • JSON syntax differs from a printed Python dictionary.
  • load and dump use files; loads and dumps use strings.
  • Choose an orientation matching the table layout.
  • Wrap JSON text in StringIO for read_json and preserve identifier types.
  • JSON Lines uses one object per line and supports chunked reading.
  • Use ISO date output for readable exchanged timestamps.

4.2 Choose what one row of nested data represents

Nested JSON can describe an order, its customer and several items in one object. Before flattening it, decide the grain: what one row represents. The grain determines which amounts can be summed.

Flatten nested objects first

Consider two orders. Order 501 belongs to Ana and has items A1 (quantity 2, price 3.5) and B7 (quantity 1, price 10.0). Order 502 belongs to Ben and has A1 (quantity 4, price 3.5). Their customer details are nested objects and their items are lists.

orders = [
    {"order_id": 501,
     "customer": {"name": "Ana", "country": "PT"},
     "items": [{"sku": "A1", "qty": 2, "price": 3.5},
               {"sku": "B7", "qty": 1, "price": 10.0}]},
    {"order_id": 502,
     "customer": {"name": "Ben", "country": "CA"},
     "items": [{"sku": "A1", "qty": 4, "price": 3.5}]}
]
order_rows = pd.json_normalize(orders)

This produces two rows and four columns: order_id, items, customer.name and customer.country. The nested customer fields become columns with dotted names. The item lists remain in cells; normalization does not automatically turn every list into rows.

Expand a list with parent information
items = pd.json_normalize(
    orders,
    record_path="items",
    meta=["order_id", ["customer", "name"]]
)

record_path chooses the list whose entries become rows. meta copies parent values onto each row, with a list of keys for a nested path. The result has three item rows: two for Ana's order and one for Ben's. The revenue is quantity times price: 7.0, 10.0 and 14.0, totaling 31.0.

If an order-level shipping charge is 4.00, it repeats on both item rows for order 501. Summing those repeated charges gives 8.00 for one order. Keep order-level amounts in a separate orders table when you also need an item table; retain order_id to connect them.

Control names and missing fields

sep="_" creates names such as customer_name. record_prefix="item_" distinguishes item fields from parent fields with the same name. max_level=0 leaves nested dictionaries intact.

An ordinary nested field absent from one record becomes missing in its output column. A missing field requested through meta raises KeyError by default; errors="ignore" allows missing metadata and fills it with NaN. A missing list named by record_path still needs to be corrected.

Unwrap API responses before flattening

An API can return an envelope containing count, next and results. Pass data["results"] to pd.json_normalize to flatten the records. Passing the envelope itself normalizes one wrapper object, leaving its results list packed into a cell. Keep pagination metadata available for fetching later pages, but build the analysis table from the actual record list.

Key Takeaways

  • Decide whether each row represents a parent or a list entry.
  • json_normalize expands nested objects; record_path expands a chosen list.
  • meta repeats parent fields on each child row.
  • Parent-level amounts can be double-counted after list expansion.
  • Flatten the records inside an API envelope, not the wrapper.

4.3 Request a complete, checked API result

A web API accepts an HTTP request at an endpoint and returns a status code, headers and a body. Many APIs use JSON bodies, but a response arriving successfully does not mean it contains the data or all the records you need.

Send parameters and check the response
import requests

resp = requests.get(
    url,
    params={"city": "Lima", "units": "metric"},
    timeout=10
)
resp.raise_for_status()
data = resp.json()
df = pd.json_normalize(data["results"])

Here url is the API's documented endpoint. params encodes the query string, so spaces and special characters in values are handled correctly. Requests has no timeout by default. A single timeout value controls connection and read waiting; it is not a deadline for the entire response download.

Call raise_for_status() before using the body. It raises an HTTP error for 4xx and 5xx responses. A JSON error message can parse successfully while still describing a failed request; conversely, a 200 response can contain non-JSON text, making resp.json() fail. Inspect resp.text when the response format is unexpected.

StatusMeaning to investigate
200Request succeeded
400Request details are invalid
401Credentials are missing or invalid
403Access is forbidden
404Requested resource was not found
429Request rate is too high
5xxServer-side failure
Keep credentials separate

Use the authentication method the API documents. For a bearer token, read a key from an environment variable and send it in a header:

import os

key = os.environ["WEATHER_API_KEY"]
headers = {"Authorization": "Bearer " + key}

Keep keys out of saved code and notebooks. If a key has been shared or committed, revoke and replace it. A key grants access; hiding a displayed value later does not undo its exposure.

Continue until all pages are read

Follow the API's documented next-page mechanism, whether it uses page numbers, offsets or a next URL. Collect each page's records and stop at its stated end condition. A total of 230 records with 100 per page requires pages of 100, 100 and 30. The first page can be perfectly valid while the dataset is incomplete.

Compare the collected count with a reported total when available. Respect rate limits: 429 calls for waiting before another request, and Retry-After can specify the delay. That header can contain seconds or an HTTP date. Save raw responses for reproducible analysis and to avoid downloading the same data on every rerun.

Recognize other web table formats

pd.read_html(url) returns a list of DataFrames, one for each matching HTML table. match="Population" restricts tables by their text. It needs an HTML parsing dependency such as lxml or BeautifulSoup with html5lib. pd.read_xml reads repeated XML elements as rows, using lxml or parser="etree". Check a site's terms before scraping and prefer an official download or API when available.

Key Takeaways

  • Send query values with params and set an explicit timeout.
  • Check HTTP status before parsing the expected response body.
  • Keep keys in environment variables and replace exposed keys.
  • Follow pagination to the end and verify the collected count.
  • Respect rate limits and save raw responses for reproducibility.
  • read_html returns a list of tables; XML has a separate reader.
5

Store data in the right file format

Saving a table is a choice about its next use. A colleague may need a readable CSV or workbook, while your next analysis needs exact types and full precision. You will control CSV output, compare common exchange and binary formats, and use Parquet for typed tables. You will also select columns and partitions during reading and keep dataset files consistent as more data is added.

5.1 Write CSV without accidental extra data

A CSV export should preserve the values the recipient needs and make its conventions clear. Choose whether the row index is data, how missing values appear, and whether output is for precise analysis or a rounded display.

Choose what becomes a column
df.to_csv("weather_processed.csv", index=False)

The default is to write the index. For a table with an ordinary numbered index, this adds an unnamed first field; a later read_csv can show it as "Unnamed: 0". index=False leaves those row numbers out. When the index contains meaningful labels, keep it and read it back with index_col=0.

Missing values normally become empty fields. na_rep="NA" makes them visible, but the receiving reader must interpret that marker correctly. In a city table with Lyon at 21.5 °C and Osaka at 18.25 °C, a missing rainfall value for Osaka should stay distinct from zero rainfall.

Match the recipient's text convention
df.to_csv(
    "weather_export.csv",
    index=False,
    sep=";",
    decimal=",",
    na_rep="NA",
    date_format="%Y-%m-%d",
    encoding="utf-8"
)

The separator and decimal options produce values such as Lyon;21,5;0,0. ISO date output keeps day and month unambiguous. Use encoding="utf-8-sig" when a receiving spreadsheet program needs a BOM to recognize UTF-8.

float_format="%.1f" writes one decimal place. The value 18.25 becomes "18.2" under this formatting, and the discarded precision cannot be recovered from the CSV. Keep full precision for analysis data; create a separate rounded report when needed.

Check what survives a round trip

CSV stores characters without pandas dtype metadata. Consider four columns: an identifier "02139", a datetime, an ordered category A < B < C, and nullable integers with a gap. A default CSV read can return integer 2139, date text, plain category labels without their order, and floating-point numbers for the counts.

A read that completes successfully has therefore not necessarily restored the original DataFrame. Keep the options needed to reconstruct the data, including text identifiers, date parsing and missing markers. Category order also needs to be defined again. For repeated analysis where these types matter, Parquet can preserve them directly.

Append records and protect raw input
df.to_csv(
    "daily_results.csv",
    mode="a",
    header=False,
    index=False
)

This adds rows to an existing file. Keep column order and conventions consistent with that file. With header=True, an append writes another header into the middle, and the next reader can treat it as a record. For a new file, write the header once before later appends.

Keep received or downloaded files unchanged in a raw-data location. Write derived results separately under descriptive names. Reopening a processed export should check its row count, columns, missing values and representative values, including leading zeros and dates.

Key Takeaways

  • Omit a default row index with index=False.
  • Choose missing markers, encoding and number conventions for the recipient.
  • Output rounding permanently removes precision.
  • CSV round trips need explicit reading options to restore types.
  • Append without repeated headers and keep raw files unchanged.

5.2 Choose a format for the next use

The best storage format depends on who reads the data next and what must survive the exchange. A table sent to a colleague, a nested API response and a typed analysis dataset have different needs.

Compare text and binary storage

Text formats encode visible characters. CSV is easy to inspect and widely supported; JSON naturally represents nested objects and arrays. CSV has no column-type schema, and ordinary JSON value types do not preserve every pandas dtype. Re-reading them requires parsing and can need explicit type choices.

Binary formats encode data for software to read directly. Formats such as Parquet and Feather store a schema describing columns and types, reducing the need to infer types again. Type support still depends on the format and reader: arbitrary Python objects do not become portable merely because the file is binary.

A row-oriented layout keeps a record's fields together. A columnar layout keeps values from the same column together. Analysis often needs a few columns from many rows, so columnar readers can skip unneeded columns. Similar adjacent values also compress well. File size and speed depend on the data; a compression result for one table is not a fixed ratio for all tables.

Match each format to a job
FormatA useful jobMain consideration
CSVSimple table exchangeReconstruct types on reading
ExcelReports used in spreadsheetsLayout and spreadsheet limits matter
JSONNested records and web servicesChoose the object and table layout
ParquetStored analysis datasetsTyped, columnar, compressed and widely supported
FeatherFast DataFrame interchangeArrow-based storage for compatible tools
picklePersonal temporary Python objectsTrust and version compatibility matter
HDF5Several large scientific datasetsHierarchical organization; PyTables for pandas
DatabaseShared querying and updatesConnections, permissions and transactions

Parquet is an open format used by pandas, R, Spark and DuckDB. Feather uses Arrow IPC and is useful for fast exchange between Python and R or between local steps. to_feather and read_feather provide that path. HDF5 groups several datasets in one file; pandas's to_hdf requires PyTables.

Understand pickle's trust boundary

pickle can save Python objects beyond ordinary tables, but loading it can execute code. Never load a pickle from an untrusted source. Use it for your own short-lived objects, and expect compatibility limits as Python and libraries change. For example, pandas 3 no longer supports reading pickles made with pandas versions before 1.0.

Decide from the required outcome

If a recipient needs to inspect a small table without special tools, CSV is practical. If they need named workbook sheets, use Excel. If you need to preserve identifiers, categories and nullable types between analysis sessions, choose Parquet. If several programs need to query and update shared records, a database fits the job better than passing around copies of a file. The format choice follows the next use, not the extension of the original input.

Key Takeaways

  • Choose a format from the recipient, data structure and required type fidelity.
  • Columnar formats support reading selected columns and useful compression.
  • Parquet suits stored analysis tables; Excel suits spreadsheet reports.
  • Feather supports fast interchange; HDF5 groups scientific datasets.
  • Untrusted pickles can execute code when loaded.
  • Databases support shared querying and updates.

5.3 Keep typed tables in Parquet

Parquet stores a table with its column types in an open, columnar format. It is useful when a checked DataFrame will be loaded repeatedly or passed to other analysis tools. pandas uses PyArrow for the examples below.

Write and verify a typed round trip
df.to_parquet("sales.parquet", engine="pyarrow")
restored = pd.read_parquet("sales.parquet", engine="pyarrow")
print(restored.dtypes)

A text identifier "02139", a datetime column, an ordered category and nullable integers can all survive this pandas-to-PyArrow-to-pandas round trip with their types. Unlike a CSV read, it does not need to guess the identifier's role or re-create the category order. Inspect types and representative values when introducing a new writer or reader.

The default index=None stores a RangeIndex compactly as metadata. Another index is written as columns and restored on reading. Use index=False when the index is not needed. That choice concerns row labels independently of the table's ordinary columns.

Read less and choose compression
small = pd.read_parquet(
    "sales.parquet",
    columns=["zip", "amount"]
)

The reader can retrieve only those columns from storage. This is different from loading the full table and selecting afterward, which has already paid the full reading cost. Column selection is especially useful for wide tables.

Snappy is the default compression codec. compression="zstd" or "gzip" often trades more writing work for smaller storage, while compression=None writes uncompressed data. Measure the tradeoff with representative data; repeated labels and random measurements do not compress alike. Install PyArrow; the alternative fastparquet engine is deprecated in pandas 3.1.

Organize a dataset into partitions
df.to_parquet(
    "sales_dataset",
    engine="pyarrow",
    partition_cols=["year"],
    index=False
)
recent = pd.read_parquet(
    "sales_dataset",
    filters=[("year", "==", 2026)]
)

The destination is a directory, with subdirectories such as year=2025 and year=2026. Reading the directory loads the dataset; a filter can avoid unrelated partitions. With this layout, PyArrow derives the year values from directory names and pandas commonly receives a categorical partition column.

Choose a partition column with a small set of useful values that you often filter on. A unique record ID makes thousands of tiny partitions, increasing file and directory work. Year or a small region set often offers a more practical split.

Add data without corrupting the dataset

A single Parquet file does not support CSV-style row appending through pandas. Write new files or partitions to the dataset directory, or read, combine and rewrite a single file. Files sharing a dataset need compatible schemas. If one stores a code as text and another as an integer, loading can fail or convert values. Set consistent dtypes before writing each part and check that an added partition does not create overlapping copies of the same records.

Key Takeaways

  • Parquet preserves supported column types through compatible readers.
  • columns reads only needed columns; filters limits matching data.
  • Index storage is controlled separately from ordinary columns.
  • Partition by a few frequently filtered values, avoiding tiny files.
  • Add dataset files with compatible schemas; do not append bytes to one file.
6

Read from and write to SQL databases

Database work joins two decisions: what result to request and what change to store. You will open and close connections, read given SQL queries into pandas, and bind changing values without altering the query structure. You will then control result types and chunking, choose a table-writing mode and verify its effect, including the difference between a complete load and a repeated append.

6.1 Open a database connection and read a result

A relational database stores records in tables with named columns. A program sends a SQL query over a connection and receives a result that pandas can turn into a DataFrame. The database can select just the data needed before it travels to Python.

Start with a SQLite file
import sqlite3
import pandas as pd

con = sqlite3.connect("shop.db")
try:
    df = pd.read_sql_query(
        "SELECT region, amount FROM sales", con
    )
finally:
    con.close()

SQLite runs without a separate server and stores a database in a file. Connecting creates the file if it does not exist, so a mistyped path can open a new, empty database instead of the intended one. ":memory:" creates a temporary in-memory database. The query above returns the region and amount columns from an existing sales table; its result column names become DataFrame labels.

A SQLite connection's with block manages a transaction, not closure. Explicitly call close() when finished. A try/finally block closes the connection even if reading raises an error.

Use an engine for a server database

SQLAlchemy provides engines for systems such as PostgreSQL, MySQL and SQL Server, with a matching driver installed. A connection URL identifies the dialect, driver, server and database. Keep it in an environment variable:

import os
from sqlalchemy import create_engine

engine = create_engine(os.environ["ANALYSIS_DB_URL"])
try:
    with engine.connect() as conn:
        df = pd.read_sql_query(
            "SELECT region, amount FROM sales", conn
        )
finally:
    engine.dispose()

The connection context returns the connection to the engine's pool. dispose() releases pooled resources when the engine is no longer needed. Use a read-only account for analysis and keep credentials out of notebooks and version control. An engine URL for a local SQLite file can be "sqlite:///shop.db".

Pick the reader that matches the input
ReaderInput
read_sql_queryA SQL query and connection
read_sql_tableA table name and SQLAlchemy connection or engine
read_sqlA query or, with supported connectivity, a table name

With a plain sqlite3 connection, pass a complete query. pd.read_sql("sales", con) sends sales as SQL and fails; use pd.read_sql_query("SELECT * FROM sales", con) instead. pandas supports SQLAlchemy, ADBC and SQLite connections; an arbitrary raw driver connection is not a supported substitute just because the driver can execute SQL.

Move the result you need

A query returning selected rows and columns transfers less data than reading a whole table and discarding most of it in pandas. The given query SELECT SUM(amount) AS total FROM sales returns one aggregate value, labeled total. Reading a query result does not change the stored table. After loading, check row count and types just as you would for a file; the database's declared types and the returned pandas types are related but not identical.

Key Takeaways

  • SQLite is a local file database; server databases need a connection and driver.
  • Use complete queries with a plain SQLite connection.
  • Let a query reduce the rows and columns transferred to pandas.
  • Keep credentials separate and use read-only access for analysis.
  • Close SQLite connections and release SQLAlchemy resources.

6.2 Keep query values separate from SQL

Changing values belong in query parameters. The SQL statement defines the operation; bound parameters supply the region, threshold or other value used for this run. This preserves the query structure even when a value contains a quote.

Bind values with the connection's syntax

For SQLite:

query = "SELECT region, amount, sold_on FROM sales WHERE amount > ? ORDER BY amount DESC"
df = pd.read_sql_query(query, con, params=(70,))

For the sales amounts 120.0, 75.5, 60.0 and 210.0, this returns 210.0, 120.0 and 75.5 in descending order. The tuple (70,) has one element; (70) is just the number 70. SQLite also accepts named placeholders, for example WHERE region = :r with params={"r": "North"}.

Placeholder rules depend on the interface. psycopg uses %s or %(name)s. With SQLAlchemy, wrap a statement in text and use named parameters:

from sqlalchemy import text

query = text("SELECT region, amount FROM sales WHERE amount >= :m")
with engine.connect() as conn:
    df = pd.read_sql_query(query, conn, params={"m": 100})

Pass values through params; do not apply Python formatting to insert them into the statement.

Understand what parameterization protects

Suppose code builds a condition using an f-string and an input "x' OR '1'='1". Pasting it inside quotes changes the condition to region = 'x' OR '1'='1', which matches every row. This is SQL injection: a value has become executable query structure.

A bound parameter is compared as one value, so that same string matches only a region literally having that text. Binding also handles ordinary names containing apostrophes without hand-built quote escaping. The rule applies to inputs from files as well as user forms.

Parameters represent values, not table or column names. A parameter in place of a table name does not select that table. When a program needs a variable identifier, choose it from a fixed list controlled by the code.

Control types in the result

SQLite commonly stores dates as text. Ask pandas to parse them:

df = pd.read_sql_query(
    "SELECT sold_on, visits FROM observations", con,
    parse_dates=["sold_on"],
    dtype={"visits": "Int64"}
)

The date column becomes datetime values, and a count with SQL NULL uses nullable integers instead of becoming floating-point solely to hold gaps. Inspect the result to check conversion.

Distinguish chunks from driver buffering

chunksize=1000 returns an iterator of DataFrames containing at most 1,000 rows each. A four-row result with chunksize=3 gives pieces of three and one. Keep the connection open while consuming them. Some database drivers still buffer the entire result before pandas yields chunks; a server-side cursor or streaming configuration may also be needed to limit memory across the full connection path.

Key Takeaways

  • Bind changing values through params using the interface’s placeholder style.
  • A one-value positional tuple needs a trailing comma.
  • Parameters keep a value from changing the query structure.
  • Choose variable table and column names from a fixed approved list.
  • Parse dates and request nullable integer result types explicitly.
  • pandas chunk size does not determine how the driver buffers data.

6.3 Write tables and verify the intended change

to_sql creates a database table from a DataFrame or writes rows into an existing table. Its options decide whether existing data survives, whether the index becomes a column and how a group of writes is committed.

Choose the existing-table behavior
df.to_sql("sales", con, index=False)

The default if_exists="fail" stops when sales already exists. Choose another mode only when its effect matches the intended load:

ModeExisting table behavior
failStop without loading into that table
appendAdd rows to the existing contents
replaceDrop the table and create it again
delete_rowsRemove all rows, retain the table, then insert

delete_rows is available in pandas 3. Replacing a table removes its old definition, including keys, indexes and constraints; database-specific permissions can be affected too. Deleting rows preserves the definition but still erases every existing record. Use it for an intended full reload, not when the DataFrame contains only a new batch.

Set columns and write in a transaction

The default writes the DataFrame index as a column. An unnamed index becomes index; a named index keeps its name. index_label gives it an explicit name, and index=False excludes it. If an ID is already an ordinary column, writing default row numbers usually adds no useful information.

With SQLAlchemy, dtype can choose database types:

from sqlalchemy import types

with engine.begin() as conn:
    df.to_sql(
        "sales", conn,
        if_exists="append",
        index=False,
        dtype={"sold_on": types.Date()},
        chunksize=1000
    )

engine.begin() commits on successful exit and rolls back on an exception. For an existing table, the stored schema still governs what values can be inserted; dtype is not a command to redesign its columns. Transaction guarantees also depend on the database's support for the operations used. Appending inside a SQLAlchemy transaction keeps the example's insert load together.

chunksize groups rows into batches. method="multi" puts several rows in one INSERT statement where supported. It can improve or reduce performance depending on the database and batch size, so measure it with representative data.

Verify growth, not just completion
check = pd.read_sql_query("SELECT COUNT(*) AS n FROM sales", con)
print(check["n"].iloc[0])

For a new or fully reloaded table, compare the count with len(df). For an append, compare the increase: a table with four rows receiving two rows should contain six. The row count returned by to_sql comes from the driver's reporting; verify the stored data directly.

Running an append twice repeats the records unless the database rejects duplicates or the program selects only new records. Decide whether the operation is a full reload or a new-record append before running it again. A transaction prevents a partial load on failure; it does not make repeated successful appends unique.

Key Takeaways

  • append adds rows; replace drops the table; delete_rows keeps its definition.
  • Use index=False unless the index belongs in the stored data.
  • Use a SQLAlchemy transaction to commit or roll back a load together.
  • Verify an append by its expected increase in stored rows.
  • Repeating a successful append can duplicate records.
  • Batch size and multi-row INSERT performance depend on the database.

Loading and Storing Data in pandas examples

6 Walkthroughs

1

Build a reliable table from text

17 steps
Work from raw records to a checked DataFrame, choosing headers, number formats, types and report boundaries.
  1. 1
    IntroductionRead structure before values

    A text export leaves important choices to its reader. A comma can divide fields or occur inside a quoted name; a number can be a measurement or an identifier.

    You will first establish the records and columns, then interpret their values, and finally remove report material outside the table. Inspect the result after each decision so a successful read does not hide changed data.

  2. 2
    ExampleLoad three sales records

    The sales file has a header and three observations:

    order_id,date,region,units,price
    1001,2026-03-02,North,3,4.50
    1002,2026-03-02,South,1,12.00
    1003,2026-03-03,North,2,7.25
    

    df = pd.read_csv("sales.csv") produces shape (3, 5). units is an integer column and price is floating-point. The date-looking strings still need date parsing.

  3. 3
    ExplanationGive each inspection a purpose

    Use head() to check that fields sit under their intended names, shape to compare dimensions, and dtypes to inspect interpretation. info() adds non-null counts.

    If a numeric column is text, inspect raw values for markers or number conventions. If a file is not found, check the current working directory: changing column options cannot fix a relative path pointing to the wrong location.

  4. 4
    ChallengeKeep the first observation

    A headerless file begins V12,South,6 and has 40 observations. A default read gives 39 rows with those three values as labels. What reading change keeps all observations and supplies useful names?

    ---reveal---

    Use header=None, names=["site", "region", "units"]. The first record remains data, so the expected shape is (40, 3). Supplying replacement names with header=0 would still consume that first record.

  5. 5
    Key InsightQuotes define the field boundary

    The record "Smith, Jane",Boston,10 has three fields. The comma inside the quotes is part of the name. A doubled quote inside a quoted field represents one literal quote.

    Quoted fields can also contain a line break. Let read_csv interpret records: splitting each physical line on commas can create both false columns and false records.

  6. 6
    ExampleIdentify three different symbols

    The product export contains Tea;3,50;1.200. A semicolon separates its fields, a comma marks the fractional part of price, and a point groups quantity digits.

    df = pd.read_csv(
        "products.csv", sep=";",
        decimal=",", thousands="."
    )
    

    The values become price 3.5 and quantity 1200. The separator option alone does not establish the number convention.

  7. 7
    ChallengeCatch a silent scale error

    A semicolon export documents quantities as whole units. Its raw quantity is "6.400", but a read using only sep=";" gives 6.4. What number option and expected value fix the interpretation?

    ---reveal---

    Use thousands="." to interpret the point as grouping, producing 6400. The value 6.4 is numerically valid under a decimal-point interpretation, so an exception is not needed for this error. Compare loaded values with the source.

  8. 8
    TipMatch the engine to the needed options

    The usual C engine handles common files quickly. The Python engine supports separator detection, general regular-expression separators and footer skipping. sep=None can detect a separator but can guess badly on irregular reports.

    State a separator you already know. Select engine="python" when using skipfooter; the PyArrow engine has its own option limits, including no chunksize support.

  9. 9
    ExampleMake missing markers column-specific

    The score values are 88, "n/a", "-" and 999. The last two are documented missing markers.

    df = pd.read_csv(
        "scores.csv",
        na_values={"score": ["-", "999"]}
    )
    

    The score becomes 88.0 followed by three missing values. Confine the rule to score so a legitimate 999 in another column remains data. An undeclared sentinel can distort totals and means.

  10. 10
    ExplanationPreserve codes and interpret dates

    An identifier such as "00501" needs text storage, while counts with gaps can use nullable "Int64". Dates need their own interpretation too.

    df = pd.read_csv(
        "visits.csv",
        dtype={"code": str, "visits": "Int64"},
        parse_dates=["day"], date_format="%d/%m/%Y"
    )
    

    The explicit pattern makes "03/04/2026" April 3. Inspect dtypes afterward to confirm the requested conversion actually occurred.

  11. 11
    ChallengeRespect a real label and a gap

    In a CSV, zone "NA" is a real label. Blank visits means missing and the known counts are integers. What missing-value and type choices preserve those meanings?

    ---reveal---

    Use keep_default_na=False, na_values={"visits": [""]}, dtype={"visits": "Int64"}. The zone label survives, while empty visit fields become missing integers. Leaving default markers enabled would also remove the real "NA" label.

  12. 12
    ExampleLocate the report table

    A report has three lines before its header, a # comment in its body, then observations followed by a total and a source note.

    df = pd.read_csv(
        "report.csv", skiprows=3, comment="#",
        skipfooter=2, engine="python"
    )
    

    The title lines, comment and footer are excluded. If January's observations sum to 218, retaining a total row of 218 would incorrectly make the column sum 436.

  13. 13
    Key InsightNot every broken record raises

    Extra fields can trigger a malformed-line error. Too few fields can instead produce missing trailing values: under id,name,score, the record 2,Ben loads with no score.

    Skipping malformed records also discards their observations. Check row counts and missing counts separately, and investigate a wrong separator or unquoted field before deciding that records should be dropped.

  14. 14
    ChallengeKeep positions straight

    A fixed-width export assigns positions 0–2 to a code, 3–9 to a name and 10–14 to a value. What colspecs match those fields?

    ---reveal---

    Use [(0, 3), (3, 10), (10, 15)]. Each range includes its start and excludes its end, giving widths 3, 7 and 5. Using endpoints 2, 9 and 14 would drop the last character of each field because those ends are excluded.

  15. 15
    ExplanationChoose stacked or flat labels

    When two header rows describe groups and years, header=[0, 1] creates column labels with two levels. A sales column can then be identified by ("sales", "2026").

    If the analysis needs ordinary flat names, skip both header rows and supply names such as "region", "sales_2025" and "sales_2026". Check that neither header was left among the observations.

  16. 16
    ChallengeCombine layout and value choices

    An export has one title line, then header code;amount;day. A record is 00018;2.100,50;11/12/2026. Amounts use point grouping and decimal commas; dates are day-first. State the essential read choices.

    ---reveal---

    Use skiprows=1, sep=";", thousands=".", decimal=",", dtype={"code": str}, parse_dates=["day"], date_format="%d/%m/%Y". The record keeps code "00018", amount 2100.5 and December 11 as its date.

  17. 17
    RecapCheck the imported meaning

    Match record boundaries, headers and table limits first. Then set number conventions, missing markers, identifier types and dates.

    Inspect dimensions and types, compare selected raw values, and check gaps and totals. A parser can finish successfully while losing a leading zero, swapping a date or counting a report total as an observation. These checks tell you whether the imported table means what the file means.

2

Decode text and process it in pieces

13 steps
Diagnose damaged characters, then process large or compressed inputs without keeping the whole dataset.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionTwo separate reading problems
  2. 2
    ExampleFollow a character into bytes
  3. 3
    ExplanationUse markers and documentation
  4. 4
    ChallengeInterpret the signature
  5. 5
    ExampleRepair the original interpretation
  6. 6
    TipDo not erase unreadable characters
  7. 7
    ChallengeChoose evidence over silence
  8. 8
    ExplanationMeasure the loaded table
  9. 9
    ExampleKeep a running sum and count
  10. 10
    ChallengeWeight observations equally
  11. 11
    Key InsightCompression and chunking solve different costs
  12. 12
    ChallengeKeep the memory benefit
  13. 13
    RecapKeep bytes and partial results trustworthy
3

Read a workbook and build a clear report

11 steps
Locate worksheet observations, understand stored cells, and save several tables without losing sheets.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionSeparate the table from its presentation
  2. 2
    ExampleSelect the observations in Q1
  3. 3
    ExplanationRead the stored value
  4. 4
    Key InsightA formula is not a calculation request
  5. 5
    ChallengeExplain two suspicious cells
  6. 6
    TipCheck the sheet collection
  7. 7
    ExampleWrite two sheets through one writer
  8. 8
    ExplanationChoose how an existing sheet changes
  9. 9
    ChallengeAvoid leftover rows
  10. 10
    ChallengeBuild a report from several source sheets
  11. 11
    RecapVerify the workbook at both ends
4

Turn API records into a table with the right grain

16 steps
Parse JSON, expand nested records, and collect complete API results with checks at each boundary.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionFrom response text to observations
  2. 2
    ExampleTranslate JSON values into Python
  3. 3
    ExplanationChoose a table layout explicitly
  4. 4
    ChallengePreserve a JSON identifier
  5. 5
    TipMake exchanged JSON readable and valid
  6. 6
    ExampleStart with one row per order
  7. 7
    ExampleExpand the chosen list
  8. 8
    Key InsightMatch totals to the row grain
  9. 9
    ChallengeKeep a zero-item parent visible
  10. 10
    ExampleCheck status before building a table
  11. 11
    TipProtect access and respect waiting
  12. 12
    ChallengeAccount for every page
  13. 13
    ExplanationUnwrap records and inspect gaps
  14. 14
    ConnectionRecognize a different web format
  15. 15
    ChallengeSeparate collection from normalization
  16. 16
    RecapCheck each boundary in order
5

Choose what your saved file preserves

13 steps
Control CSV exports, compare storage choices, and read useful parts of a typed Parquet dataset.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionSave for the next reader
  2. 2
    ExampleWrite the intended CSV fields
  3. 3
    Key InsightAn export can discard precision and types
  4. 4
    ChallengeAppend only records
  5. 5
    ExplanationRead columns without reading every field
  6. 6
    ConnectionMatch formats to activities
  7. 7
    ChallengeChoose portability and trust
  8. 8
    ExampleWrite and read a typed table
  9. 9
    ExampleUse a useful directory split
  10. 10
    ChallengeAvoid thousands of tiny pieces
  11. 11
    TipAdd files with compatible types
  12. 12
    ChallengeKeep a report and an analysis dataset
  13. 13
    RecapVerify the properties you need later
6

Read query results and verify table writes

14 steps
Manage connections, bind values, control result types, and store a batch with a checked database effect.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionA read returns data; a write changes it
  2. 2
    ExampleRead from a local SQLite database
  3. 3
    ExplanationManage engine and connection lifetimes
  4. 4
    ChallengeSend a query instead of a table label
  5. 5
    ExampleBind a changing threshold
  6. 6
    Key InsightA value cannot become query syntax
  7. 7
    ChallengePreserve types and parameter boundaries
  8. 8
    TipConsume chunks while the connection is open
  9. 9
    ExplanationDecide what happens to existing records
  10. 10
    ExampleAppend within a transaction
  11. 11
    ChallengeVerify the change and the rerun
  12. 12
    TipCheck stored results directly
  13. 13
    ChallengeKeep the definition and replace a snapshot
  14. 14
    RecapMatch the call to its database effect

Loading and Storing Data in pandas practice questions

50 Practice Questions in 5 sets

Set 1: Diagnose imports before trusting the table10 Practice Questions

Question 1 of 10

An existing table has important constraints and contains an old full snapshot. A new DataFrame is the complete replacement snapshot. What mode keeps the table definition while loading the new contents?
  1. if_exists="append"
  2. if_exists="delete_rows"
  3. if_exists="replace"
  4. if_exists="fail"
Show answerHide answer
Answer: B
delete_rows removes the previous contents and inserts the complete new snapshot while retaining the table definition. replace drops and recreates the table, risking its existing constraints and indexes. append keeps the old snapshot too, so it does not perform the requested full reload.

Question 2 of 10

A CSV record is "Field ""A,B""",7. What values should a standard CSV parser produce?
  1. Field "A and B" and 7
  2. Field A and B and 7
  3. Field ""A,B"" and 7
  4. Field "A,B" and 7
Show answerHide answer
Answer: D
The outer quotes protect the comma inside the first field, and each doubled quote becomes one literal quote. The record therefore has two fields, with the first reading Field "A,B". Splitting on every comma creates an extra field by ignoring the quoting rules.

Question 3 of 10

A semicolon file contains code;score;day and 00064;999;07/08/2026. The code is an identifier, 999 means missing only for score, and dates are day-first. What import preserves all three meanings?
  1. sep=";", dtype={"code": int}, na_values={"score": ["999"]}, parse_dates=["day"], date_format="%d/%m/%Y"
  2. sep=";", dtype={"code": str}, na_values={"score": ["999"]}, parse_dates=["day"], date_format="%d/%m/%Y"
  3. sep=";", dtype={"code": str}, na_values={"score": ["999"]}, parse_dates=["day"], date_format="%m/%d/%Y"
  4. sep=";", dtype={"code": str}, na_values={"code": ["999"]}, parse_dates=["day"], date_format="%d/%m/%Y"
Show answerHide answer
Answer: B
The code must remain text, the sentinel rule belongs to score, and the date format must put day before month. Together those settings retain "00064", mark the score missing and interpret the date as August 7. A month-first format silently changes this valid date to July 8.

Question 4 of 10

Python’s open() leaves an initial UTF-8 BOM in the first header under plain UTF-8 decoding. What encoding setting removes that marker?
  1. encoding="utf-8-sig"
  2. encoding="utf-16-le"
  3. encoding="cp1252"
  4. encoding="ascii"
Show answerHide answer
Answer: A
utf-8-sig recognizes and removes an initial UTF-8 BOM while decoding the remaining text as UTF-8. Switching to a different encoding changes the interpretation of the actual file bytes. In particular, Windows-1252 does not turn a UTF-8 signature into clean header text.

Question 5 of 10

A huge CSV has a numeric amount column with some gaps. The program needs its overall mean with limited memory. What design remains correct when chunks contain different valid counts?
  1. Accumulate chunk means and divide by the number of chunks.
  2. Accumulate sums and divide by the requested chunk size.
  3. Accumulate each chunk’s sum and nonmissing count, then divide once.
  4. Retain every chunk and concatenate before calculating the mean.
Show answerHide answer
Answer: C
The total sum divided by the total nonmissing count gives each observation equal weight, while retaining only small partial results. Equal weighting of chunk means fails when valid counts differ. Keeping every chunk can give the right value but breaks the requirement to avoid holding the whole table in memory.

Question 6 of 10

A workbook stores a code as numeric 537 with display format 00000. A formula cell has no cached result. What should you expect from a pandas read that requests a text dtype for the code?
  1. The code lacks its displayed zeros, and pandas does not calculate the formula.
  2. The code gains its displayed zeros, and pandas calculates the formula.
  3. The code lacks its displayed zeros, and pandas calculates the formula.
  4. The code gains its displayed zeros, and the formula is read from its text.
Show answerHide answer
Answer: A
The numeric cell stores 537, so a text dtype can represent that stored value but cannot recover zeros supplied only by display formatting. pandas also reads formula caches rather than calculating formulas. A missing cache cannot be repaired merely by changing the code column’s dtype.

Question 7 of 10

A JSON string contains [{"device":"00091","active":true}]. How should pandas read it without treating the string as a path or dropping the identifier’s zeros?
  1. Use text directly and dtype={"device": str}.
  2. Use StringIO(text) and dtype={"device": int}.
  3. Use json.dumps(text) and dtype={"device": str}.
  4. Use StringIO(text) and dtype={"device": str}.
Show answerHide answer
Answer: D
StringIO presents the JSON text as an in-memory file, and the explicit text dtype preserves "00091". Passing the bare string to pandas 3’s reader treats it as a path. Serializing the text again produces a JSON string value, not the intended array of records.

Question 8 of 10

An API returns HTTP 200 with valid JSON and a nonempty next URL. The collected row count is below count. A colleague reports the current table as complete. What is the defect?
  1. The total should be replaced by the first-page count.
  2. The next URL must point back to collected records.
  3. HTTP success was mistaken for completion of all pages.
  4. The server’s count field shows the records are complete.
Show answerHide answer
Answer: C
HTTP 200 establishes success for that response, while next and the smaller collected count show that more records remain. Continue through the documented pages before reporting a complete collection. Replacing the total with the first page size hides missing records instead of resolving them.

Question 9 of 10

A precise analysis value is 6.347. It is exported with float_format="%.2f" and later read as a number. What value can that CSV restore?
  1. 6.347
  2. 6.35
  3. 6.34
  4. 6.3
Show answerHide answer
Answer: B
The formatter writes two decimal places, rounding 6.347 to 6.35. The extra digits are absent from the CSV and cannot be recovered by choosing a more precise dtype on reading. Truncating to 6.34 is a different operation from the requested rounding format.

Question 10 of 10

A year-partitioned dataset stores code as text in 2025 and as integers in a proposed 2026 file. The new data also contains only one row per nearly unique code. What preparation best supports reliable reading?
  1. Keep mixed code types and replace years with code partitions.
  2. Align code types and create a partition for every code.
  3. Keep mixed code types and rely on column projection to repair them.
  4. Align code types and keep the useful year partitioning.
Show answerHide answer
Answer: D
Compatible schemas prevent conflicting code interpretations across files, while year partitions retain a useful small set of filterable groups. A partition for nearly every code creates many tiny files. Reading fewer columns does not repair an incompatible type when the analysis needs the code column.
Set 2: Connect parsing choices to stored results10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A pipe-separated table stores a quoted numeric field "7,680.25". The delimiter is read correctly but the amount stays text. What additional reading option matches the number?
  1. thousands=","
  2. decimal=","
  3. thousands="."
  4. quotechar="|"
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A report starts with two title lines, then site,jan,feb. Its body contains a # note line and ends with a total plus a source note. What configuration reads only observations without treating notes as records?
  1. skiprows=3, comment="#", skipfooter=2, engine="python"
  2. skiprows=2, comment="#", skipfooter=1, engine="python"
  3. skiprows=2, comment="#", skipfooter=2, engine="python"
  4. skiprows=2, comment="#", skipfooter=2, engine="c"
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A documented UTF-8 CSV was read as Windows-1252, producing garbled names. That table was then saved correctly as UTF-8. The original download still exists. What recovery restores the intended names?
  1. Re-read the derived export as UTF-8, then save it unchanged.
  2. Re-read the original as Windows-1252, then add a UTF-8 BOM.
  3. Re-read the derived export as Latin-1, then replace invalid bytes.
  4. Re-read the original as UTF-8, then rebuild the derived export.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A workbook contains History and Current. Only Current should be replaced, with History retained. What writer setup fits?
  1. Write mode, openpyxl engine, and a Current sheet name.
  2. Append mode, openpyxl engine, and if_sheet_exists="replace".
  3. Append mode, openpyxl engine, and if_sheet_exists="overlay".
  4. Write mode, XlsxWriter engine, and index=False for Current.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A normalized parts table has rows (visit_id, visit_fee, part_cost): (51, 12, 3), (51, 12, 5) and (52, 7, 4). What is the total of visit fees plus parts for these two visits?
  1. 43
  2. 31
  3. 27
  4. 35
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A collection script has saved page 1 of an API result. Its request for page 2 gets HTTP 429 with Retry-After: 45. What continuation preserves the collection and respects the response?
  1. Wait 45 seconds, retry page 2, then follow remaining pages.
  2. Wait 45 seconds, restart page 1, and append all pages to the saved records.
  3. Request page 3 immediately and treat page 2 as an empty result.
  4. Save the 429 body as page 2, then request its next page.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

Why is loading a colleague’s unverified pickle a different trust decision from reading an ordinary CSV?
  1. Unpickling proves that the file came from its named sender.
  2. A preserved dtype makes an unverified pickle safe to load.
  3. Unpickling can execute code while loading the object.
  4. Library-version compatibility prevents code execution in a pickle.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A table has 2 million rows, 60 columns and four years. A recurring analysis needs two columns for one year. What storage and read design avoids unnecessary columns and year groups?
  1. Parquet partitioned by record ID, followed by a full dataset read.
  2. One CSV per year, followed by reading every column of every file.
  3. One Parquet file per year, followed by loading all files before filtering.
  4. Parquet partitioned by year, with a column list and year filter.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A program lets users choose a table and a threshold. Its query uses a placeholder for the table name and formats the threshold into SQL. What redesign supports the intended choices safely?
  1. Choose the table from a fixed list and bind the threshold value.
  2. Bind both the table name and threshold as ordinary values.
  3. Format both inputs after removing spaces from their text.
  4. Bind the table name but format a numeric-looking threshold.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A daily batch must be appended to an existing constrained table. A failed batch must leave no partial inserts, and a successful batch should increase the stored count by its length. What design fits?
  1. Replace in a SQLAlchemy transaction, then compare count to batch size.
  2. Append without a transaction, then compare the total with batch size.
  3. Delete all rows in a transaction, then verify growth from the old total.
  4. Append through a SQLAlchemy transaction, then verify count growth.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Resolve several loading and storage risks10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A colleague needs a spreadsheet report with named sheets for measurements and counts. What output format serves that use directly?
  1. Excel workbook
  2. JSON Lines file
  3. Feather file
  4. Parquet dataset
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A CSV has codes "0072" and "0073", nullable whole-number counts and dates "12/01/2026", "26/01/2026". The source defines day-first dates. What combination preserves these meanings?
  1. Code as text, count as int32, dates parsed with %d/%m/%Y.
  2. Code as integers, count as Int64, dates parsed with %d/%m/%Y.
  3. Code as text, count as Int64, dates parsed with %d/%m/%Y.
  4. Code as text, count as Int64, dates parsed with %m/%d/%Y.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A loader uses on_bad_lines="skip". Of 1,000 source observations, 995 load; two of those have missing trailing fields. What follows from these results?
  1. Seven observations were lost; every missing field marks a skipped record.
  2. Five observations were lost; short loaded records still need inspection.
  3. Five observations were lost; the loaded records must all be complete.
  4. Two observations were lost; the count difference only reflects empty fields.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A short file decodes without error as Latin-1, but the source encoding is unknown. What evidence would strengthen the choice?
  1. The absence of a decoding exception in the Latin-1 read.
  2. A text editor opening the file without showing its encoding.
  3. An ASCII-only header looking correct under that decoder.
  4. Export documentation and correctly decoded accented values.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A gzip CSV is processed in chunks. A colleague sums amounts but divides by the number of rows, including missing amounts, and retains every chunk in a list. What paired correction meets a mean-only, limited-memory task?
  1. Count nonmissing amounts and retain only sums and counts.
  2. Count every row and retain only the average of chunk means.
  3. Count nonmissing amounts and concatenate all retained chunks.
  4. Count chunks and retain their sums without observation counts.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A worksheet’s formula total displays 90, but the last saved cache is 74. A 16-digit device ID was entered as a number. What two limits must be handled before relying on the import?
  1. Formula caches need updating; a text read alone restores the full ID.
  2. The displayed formula is current; the original full ID needs text storage.
  3. Formula caches need updating; the original full ID needs text storage.
  4. The displayed formula is current; a text read alone restores the full ID.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

An envelope contains three orders with 2, 1 and 0 items. The item table repeats each order’s delivery fee. The analyst needs both order count and total delivery fees. What design avoids losing or repeating orders?
  1. Count item rows and sum every repeated fee in the item table.
  2. Keep only orders appearing in the item table and take the largest fee.
  3. Use the item table’s row count as order count and divide fees by three.
  4. Keep an order table for counts and fees, linked to a separate item table.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A processed CSV has a duplicate header inside the records, rounded measurements and damaged leading-zero IDs after rereading. Which set of changes addresses the three causes?
  1. Append with headers, export full precision, and read IDs as text.
  2. Append without headers, export full precision, and read IDs as text.
  3. Append without headers, widen the read float dtype, and read IDs as integers.
  4. Append without headers, export rounded values, and convert IDs to text afterward.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A stored table has 140 rows. A seven-row batch contains only new records and must keep existing rows and constraints. After loading, what mode and count check fit?
  1. Use replace and verify that the stored count is seven.
  2. Use append and verify that the stored count is 147.
  3. Use append and verify that the stored count is seven.
  4. Use delete_rows and verify that the stored count is 147.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A constrained table has 80 rows. A 12-row append inside a supported transaction fails after inserting five rows, and the exception leaves the transaction block. What count should remain, and what would a successful retry produce?
  1. 80 after rollback; 92 after one successful retry.
  2. 85 after failure; 97 after one successful retry.
  3. 80 after rollback; 80 after one successful retry.
  4. 92 after failure; 104 after one successful retry.
Show answerHide answer

Save this lesson to see this answer.

Set 4: Read the data and check its meaning10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A headerless file starts with S14,East,8. How should it be read so that this record remains data?
  1. header=0, names=["site", "zone", "count"]
  2. header=None, names=["site", "zone", "count"]
  3. header=1, names=["site", "zone", "count"]
  4. skiprows=1, names=["site", "zone", "count"]
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A semicolon file records sensor;distance_m followed by R8;2.450,75. How should the distance become 2450.75?
  1. sep=";", decimal=".", thousands=","
  2. sep=",", decimal=",", thousands="."
  3. sep=";", decimal=",", thousands=" "
  4. sep=";", decimal=",", thousands="."
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

In UTF-8, each ASCII letter uses one byte and "é" uses two. How many bytes encode "été"?
  1. 5 bytes
  2. 3 bytes
  3. 4 bytes
  4. 6 bytes
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A worksheet has a title in row 1, a blank row 2, labels in row 3, three observations in rows 4–6 and a total in row 7. What reading options isolate the observations?
  1. skiprows=3, nrows=3
  2. skiprows=2, nrows=4
  3. skiprows=2, nrows=3
  4. skiprows=1, nrows=3
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A log has one complete JSON object on each line and no enclosing array. What pandas reading option matches that layout?
  1. orient="split"
  2. lines=False
  3. lines=True
  4. orient="index"
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A response has keys count, next and results; each entry in results is a nested equipment record. What should be passed to json_normalize for an equipment table?
  1. data["results"]
  2. data
  3. data["count"]
  4. data["next"]
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A CSV reimport contains a new "Unnamed: 0" column holding only the old default row numbers. What export change prevents it?
  1. Use header=False.
  2. Use na_rep="0".
  3. Use mode="a".
  4. Use index=False.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A team needs a broadly supported file for repeated analysis that preserves an ordered category and nullable counts. What format fits best?
  1. CSV text
  2. Parquet
  3. JSON records
  4. Excel workbook
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A database has an existing readings table and con is a plain SQLite connection. What call retrieves it as a DataFrame?
  1. pd.read_sql("readings", con)
  2. pd.read_sql_table("readings", con)
  3. pd.read_sql_query("readings", con)
  4. pd.read_sql_query("SELECT * FROM readings", con)
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A SQLite query contains WHERE site = ?. How should the single value "West" be passed?
  1. params=("West",)
  2. params=("West")
  3. params={"site": "West"}
  4. params="West"
Show answerHide answer

Save this lesson to see this answer.

Set 5: Preserve values across files and connections10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

In a CSV, "NA" is a valid zone label and an empty count means missing. What configuration preserves both meanings?
  1. keep_default_na=True, na_values={"count": [""]}
  2. keep_default_na=False, na_values={"zone": ["NA"]}
  3. keep_default_na=False, na_values={"count": [""]}
  4. keep_default_na=True, na_values={"zone": ["NA"]}
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A CSV header has four fields. A later record supplies only three and loads without an error. What should you check?
  1. The last column’s missing count and that raw record.
  2. The missing count only, ignoring the source layout.
  3. Only rejected-line warnings for the short record.
  4. The overall row count, as a completeness check.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A UTF-8 source name appears as "André" after a Windows-1252 read. What is the appropriate repair?
  1. Read the altered table again with Latin-1.
  2. Replace every non-ASCII character with a blank.
  3. Save the garbled table with a UTF-8 BOM.
  4. Read the original file again with UTF-8.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

One chunk has nonmissing values 2, 6 and 10; a second has 18. What is the overall mean?
  1. 12
  2. 9
  3. 6
  4. 18
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

Two tables must be saved on separate sheets of one new workbook. What writing approach keeps both?
  1. Call to_excel twice with the same file path.
  2. Write both through one ExcelWriter context.
  3. Write the second table with header=False to that path.
  4. Open a fresh writer for each table in write mode.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

An API reports 275 matching records and returns pages of at most 80 records. How many requests are needed to collect the complete result?
  1. 4 requests
  2. 3 requests
  3. 5 requests
  4. 275 requests
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A Parquet dataset is partitioned into year directories. An analysis needs only 2024 records and two columns. What read makes use of both features?
  1. pd.read_parquet(path, columns=["year"], filters=[("site", "==", 2024)])
  2. pd.read_parquet(path, columns=["site", "value", "year"])
  3. pd.read_parquet(path, filters=[("year", "!=", 2024)])
  4. pd.read_parquet(path, columns=["site", "value"], filters=[("year", "==", 2024)])
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A SQLite connection is used inside with con:. What must still happen after the database work is finished?
  1. Recreate the connection to commit.
  2. Dispose of the connection pool.
  3. Explicitly close the connection.
  4. Reopen to release the transaction.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A SQLite result contains ISO date text in day and integer counts with NULL in n. A script must select a site supplied at runtime without changing the query structure. What combination fits?
  1. Format the site into SQL, parse day, and set n to Int64.
  2. Bind the site with params, keep day as text, and force n to int64.
  3. Bind the site with params, parse day, and set n to Int64.
  4. Bind a table name with params, parse day, and set n to Int64.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A table has 32 rows. A five-row batch is appended and then appended again after a successful first run. No uniqueness constraint rejects it. What count and conclusion fit?
  1. 42 rows; successful reruns can duplicate the batch.
  2. 37 rows; the second append replaces the first batch.
  3. 42 rows; a transaction always detects duplicate records.
  4. 32 rows; append requires dropping the table beforehand.
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

91 Key Terms, each with its definition

A

API envelope
An API envelope is a wrapper object containing record data together with information such as a result count and next-page location.
Flatten the envelope’s results list while retaining its next-page value for another request.
API key
An API key is a credential sent by a client using the API’s documented authentication method to obtain authorized access.
Read a private key from an environment variable instead of saving the key inside a notebook cell.
Append
An append adds new rows to an existing table without clearing its previous records, so repeating a batch can add duplicate records.
A table with 11 rows has 15 after four successful inserts, and can have 19 after repeating that append.
Append mode
Append mode opens an existing workbook for updates, allowing sheets to be added or handled according to a sheet-collision policy.
An openpyxl writer in append mode can replace one existing sheet in a workbook while retaining the workbook’s other sheets.
ASCII
ASCII defines 128 basic characters whose byte values are shared by UTF-8 and several common Western single-byte encodings.
An English-only header can appear correct even when the encoding used for later accented names is wrong.

B

Bound parameter
A bound parameter supplies a data value separately from SQL syntax, preventing characters in that value from redefining the query.
A region name containing an apostrophe remains a single comparison value when passed as a parameter.
Byte
A byte is a unit of stored data with 256 possible values, from 0 through 255, used as part of the representation of text.
Four visible characters in a name can require five bytes when one character uses two UTF-8 bytes.
Byte order mark
A byte order mark, or BOM, is an initial marker used by some text files to identify encoding information such as UTF-16 byte order.
Using utf-8-sig with Python text reading removes a leading UTF-8 BOM from the first header.

C

Cached formula result
A cached formula result is the value stored alongside a spreadsheet formula for a reader to use without calculating it again.
A script-generated workbook may show missing formula data because no current result was saved.
Categorical column
A categorical column stores values through a defined set of labels, often saving memory when many rows repeat a few labels.
Four regional labels repeated across thousands of records are a useful candidate for categorical storage.
Chunk
A chunk is one bounded group of records yielded by an iterative reader, allowing a program to work on part of a file at a time.
A 13-row input read in chunks of five gives DataFrames of five, five and three rows.
Columnar storage
Columnar storage keeps a column’s values together, supporting selected-column reads and compression of similar adjacent values.
An analysis needing two fields can avoid reading the other columns of a wide Parquet dataset.
Compression
Compression encodes data in fewer stored bytes, reducing file size while requiring decompression before its values can be used.
pandas can decompress a .csv.gz file during reading without first creating an uncompressed copy.
Compression codec
A compression codec is an algorithm used to compress and decompress stored data, trading file size against processing costs.
Snappy is the pandas Parquet default; another codec can give smaller files with a different writing cost.
Connection
A connection is an active interface through which a program sends database operations and receives their results.
Keep the connection open until a chunked query result has been fully consumed, then close it.
CSV
A CSV file is a text file of records whose fields are separated by a delimiter, with quotes protecting delimiters inside fields.
An address containing a comma stays in one field when the address is correctly quoted in the CSV.
CSV round trip
A CSV round trip writes a table as text and reads it again, requiring reconstruction of types that CSV does not store as metadata.
An ordered category can return as ordinary text even when every visible label remains unchanged.

D

Database driver
A database driver is the library that implements communication between Python’s database interface and a particular database system.
A PostgreSQL SQLAlchemy URL can select psycopg, which must also be installed for the connection.
Date format
A date format is a pattern that tells a parser how date components are arranged, such as day, month and four-digit year.
The pattern %d/%m/%Y makes "09/10/2026" October 9 instead of September 10.
Decimal mark
A decimal mark separates the whole and fractional parts of a number; pandas can interpret a chosen mark during text parsing.
With a decimal comma, "8,75" represents the same value as 8.75 in Python output.
Decoding
Decoding converts stored bytes into text under a specified encoding, determining which characters appear in the result.
Opening a UTF-8 file with a legacy decoder can produce garbled accents without raising an error.
Deep memory usage
Deep memory usage counts memory for stored values, including the contents of text objects, beyond the shallow size of their arrays.
Use a deep memory report to compare repeated region names stored as text and as categories.
Delimiter
A delimiter is a character or pattern marking the boundary between fields, such as a comma, tab, pipe or semicolon.
A semicolon-separated file needs sep=";" even if its file extension is .csv.
Display format
A display format changes how a stored cell value appears, such as a percentage or padded code, without changing that underlying value.
A cell displayed as "15%" stores 0.15, so the loaded value is a proportion rather than the number 15.

E

Encoding
An encoding is a rule for representing characters as bytes and interpreting those bytes as characters when they are read.
The same name can occupy different byte sequences when saved as UTF-8 and as Windows-1252.
Endpoint
An endpoint is a documented URL at which an API accepts a request for a particular resource or operation over HTTP.
An endpoint can accept a city parameter and return matching measurement records in a JSON response.
Excel engine
An Excel engine is a library pandas uses to read or write a spreadsheet format, with support depending on the file type.
A missing openpyxl installation can prevent reading an .xlsx file even when pandas itself is installed.
ExcelWriter
An ExcelWriter manages a workbook-writing session so several DataFrames can be placed on different sheets before the file is closed.
Writing two tables through one writer keeps both worksheets in the same completed report workbook.

F

Feather
Feather is an Arrow IPC-based binary format for fast interchange of typed DataFrames between compatible analysis tools.
A local Python step can save a Feather table for a later step or a compatible R workflow.
Fixed-width file
A fixed-width file stores fields at specified character positions instead of separating them with a delimiter character.
Use explicit widths when an equipment export reserves four characters for a code and seven for a name.
Footer
A footer is trailing report material outside the observation table, such as totals, source notes or explanations of the export.
Skip the final two report lines when they contain a total and a source note rather than observations.

H

Half-open range
A half-open range includes its starting position and excludes its ending position, as used for fixed-width column boundaries.
The range (2, 7) selects five character positions, ending just before position 7.
HDF5
HDF5 is a hierarchical binary format that can organize several datasets within one file, often used for large scientific data.
pandas requires PyTables to write several analysis datasets using its HDF5 interface.
Header
A header is a row of field labels that a reader uses as column names instead of treating those labels as an observation.
For a file without a header, supply column names so the first measurement remains in the table.
HTTP status code
An HTTP status code is a response number reporting the request’s outcome, with 4xx and 5xx codes indicating error classes.
Check for a failed status before converting a JSON error message into what looks like a data table.

I

Identifier
An identifier is a label for a record or entity whose digits can carry meaning without representing a quantity for arithmetic.
Reading an equipment code such as "00028" as text keeps the zeros needed to match it with the same code in a source list.
Index export
An index export writes DataFrame row labels into an output column, which is useful only when those labels belong in the exchanged data.
Exclude an ordinary numbered index to avoid a new "Unnamed: 0" column after rereading CSV.

J

JSON
JSON is a text format for objects, arrays, double-quoted strings, numbers, booleans and null, often used for exchanged nested records.
A JSON API can return a list of station objects, each containing a name and a series of temperatures.
JSON array
A JSON array is an ordered sequence of values enclosed in square brackets, converted to a Python list during parsing.
A temperature array can mix numeric observations with null for a missing measurement.
JSON Lines
JSON Lines is a text layout with one complete JSON object on each line, without one outer array enclosing all records.
Large log exports can be read in chunks when pandas is told that the input uses JSON Lines.
JSON object
A JSON object is a collection of string-named values enclosed in braces, which Python’s JSON parser converts to a dictionary.
An object can map "active" to true and "name" to a station’s text label.
JSON orientation
A JSON orientation specifies how a table’s rows, columns, labels and values are arranged within a JSON representation.
The records orientation writes each observation as an object, while split keeps labels and data separately.

L

Latin-1
Latin-1 is a single-byte encoding that maps every byte value to a character, including control characters in part of its range.
A Latin-1 read can finish without errors while still turning an intended symbol into the wrong character.

M

Malformed line
A malformed line is a record the parser cannot fit to the expected layout, such as one with more fields than its header describes.
An unquoted delimiter inside a name can make a valid observation appear to contain an extra field.
Merged range
A merged range combines several spreadsheet cells visually while keeping the stored value in its top-left cell.
A merged regional label can leave blank entries in subsequent rows when the table is read into pandas.
Missing-value marker
A missing-value marker is a source value that stands for an absent observation and is converted to a missing value while reading.
If "-" means no score, declaring it missing prevents it from keeping the score column as text.
Missing-value representation
A missing-value representation is the text written for an absent value, such as an empty field or a chosen export marker.
Writing missing rainfall as "NA" keeps it distinct from a recorded zero when the recipient reads it correctly.
Mojibake
Mojibake is garbled text caused by interpreting encoded bytes under the wrong rule even when the decoder reports no error.
A name containing "Ã" in place of an accent suggests checking whether UTF-8 bytes were read as Windows-1252.
MultiIndex columns
MultiIndex columns are column labels with several levels, which pandas can build from more than one header row.
A sales table can label a column with both its measure and its year, such as ("sales", "2026").

N

Normalization
Normalization of nested JSON expands selected object fields and list records into a table with an explicitly chosen row grain.
Normalizing customer objects that contain orders can create dotted columns without expanding each order’s item list.
Nullable integer
A nullable integer is a pandas integer type that can hold missing entries as well as whole numbers, such as the dtype Int64.
A visit-count column can retain 3 and 8 as integers while representing any empty observation in it as <NA>.

O

Output precision
Output precision is the number of digits retained in written values, which can be reduced permanently by numeric export formatting.
A report rounded during writing needs a separate full-precision analysis file if the discarded digits matter.

P

Pagination
Pagination divides an API result into separately requested pages, with a documented mechanism for reaching the remaining records.
A 260-record collection returned in pages of 100 needs three requests to retrieve every record.
Parent metadata
Parent metadata consists of fields copied from a containing JSON object onto each row created from its nested record list.
An order ID copied onto each item row lets the items be linked back to their original order.
Parquet
Parquet is an open, typed columnar file format with compression and broad support for reading and storing analysis tables.
An identifier and a nullable count can keep their types through a compatible pandas Parquet round trip.
Parsing engine
A parsing engine is the implementation that reads a text layout into values, with its own speed and supported option set.
A report needing skipfooter uses the Python engine because the C engine does not support that option.
Partial aggregate
A partial aggregate is a reduced result for one data piece that can be combined by a suitable rule with results from other pieces.
Chunk sums add directly, but an overall mean needs the combined sum and nonmissing count.
Partitioned dataset
A partitioned dataset divides table files among directories by selected field values, enabling readers to skip unrelated groups.
Directories named year=2025 and year=2026 let a year filter focus on the needed portion.
Pickle
A pickle is a serialized Python object representation that can execute code during loading and depends on compatible libraries.
Use a trusted personal pickle for a temporary object, while choosing a portable table format for exchange.
Placeholder
A placeholder marks the position of a bound value in SQL, using the syntax required by the driver or query interface.
SQLite accepts ? for positional values and :name for values supplied in a dictionary.
Projection
Projection selects the columns to read from a stored table, allowing a columnar reader to leave unrelated columns on disk.
Pass a column list to read_parquet when an analysis only needs region and amount.

Q

Quoting
Quoting encloses a text field so delimiters or line breaks inside it are treated as content instead of record structure.
The field "Harbor, West" keeps its comma inside one location name during a CSV import.

R

Rate limit
A rate limit restricts the number of requests a client may send in a period, often signaling excess requests with HTTP 429.
Wait as directed by Retry-After before retrying a request rejected for exceeding the allowed rate.
Raw data
Raw data is the unchanged input received or downloaded for an analysis, retained separately from derived and cleaned output files.
Keep the received measurement file so a later decoding or parsing correction can start from its original bytes.
Record
A record is one complete entry in a delimited file, made up of fields; quoted content can make it span more than one physical line.
A comment with an embedded line break can occupy two physical lines while still belonging to one record.
Record path
A record path selects the nested list whose entries become output rows when pandas normalizes a collection of JSON objects.
Setting record_path="items" creates an item row for each element of an order’s item list.
Relational database
A relational database stores records in tables with named columns and lets programs retrieve or change data through SQL operations.
A query can return only the required rows and columns before pandas builds an analysis table.
Replacement character
The replacement character, "�", marks content a decoder could not interpret when it was instructed to replace invalid bytes.
A name loaded as "Ren�" has lost character information; keep the original bytes for a corrected read.
Request timeout
A request timeout limits connection or read waiting during an HTTP request, without imposing a deadline on the entire download.
Set a timeout so an unresponsive connection does not keep an API collection script waiting indefinitely.
Rollback
A rollback cancels uncommitted changes in a transaction when it cannot complete successfully, restoring the prior committed state.
If a supported insert load fails inside an engine transaction, its earlier inserts can be rolled back.
Row grain
The row grain states what one table row represents, which determines how repeated labels and amounts should be interpreted.
A row for each order item carries a different counting unit from a row for each complete order.

S

Schema
A schema describes a dataset’s structure, including column names and types that compatible readers use to interpret stored values.
A shared dataset needs compatible code-column types across its files to avoid failed or changing reads.
Sentinel value
A sentinel value is a designated code for a special meaning, such as unknown, that can otherwise look like an ordinary measurement.
A documented score of 999 for unknown must be declared missing before calculating a meaningful mean.
Serialization
Serialization converts in-memory objects into a stored or exchanged representation, such as writing Python values as JSON text.
Use json.dump to serialize records into an open UTF-8 file instead of writing a Python dictionary’s repr.
Server-side cursor
A server-side cursor allows a database interface to retrieve a result progressively instead of buffering the whole result at once.
pandas chunking may still need streaming support to avoid full-result buffering by the database driver.
Sheet overlay
A sheet overlay writes values into an existing worksheet without clearing every old cell outside the newly written area.
Overlaying a shorter table can leave previous rows below it, so inspect the remaining sheet contents.
SQL injection
SQL injection occurs when inserted text changes an SQL operation’s structure instead of remaining an ordinary data value.
An input containing quotes and a true condition can widen a query built by string formatting.
SQLAlchemy engine
A SQLAlchemy engine configures database access through a driver and manages a pool of connections obtained when operations run.
A connection context returns its connection to the pool; disposing the engine releases pooled resources.
SQLite
SQLite is a database engine that runs without a separate server and commonly stores an entire database inside one local file.
A new file can be created by connecting to a misspelled database path, leaving the expected tables absent.

T

Table replacement
A table replacement drops an existing database table and creates it again, removing its former definition as well as its records.
Replacing a shared table can remove keys and indexes that were part of its original design.
Thousands separator
A thousands separator groups digits inside a numeric field and must be distinguished from the decimal mark and field delimiter.
A grouped value written "4.200,50" uses a point for thousands and a comma for its fractional part.
Transaction
A transaction groups database changes for a commit on success or a rollback on failure, within the database’s supported operations.
A SQLAlchemy transaction can prevent an append from leaving only some of its intended records stored.
Type inference
Type inference is the reader’s choice of a column type from its input values when the program has not specified that type.
A digit-only equipment code can become an integer unless the reader is told to preserve it as text.

U

UnicodeDecodeError
A UnicodeDecodeError occurs when a decoder encounters a byte sequence it cannot interpret under the chosen text encoding.
A Windows-1252 accented character can trigger this error when the file is opened as UTF-8.
UTF-8
UTF-8 represents Unicode characters using one to four bytes, keeping ASCII characters in one byte and supporting every Unicode character.
The letter "é" uses two bytes in UTF-8, so a character count need not match the file’s byte count.
UTF-16
UTF-16 encodes Unicode using two-byte units, with byte order that must be known or identified through a leading byte order mark.
Read a BOM-less little-endian export with encoding="utf-16-le" when that is its documented layout.

W

Weighted mean
A weighted mean gives each partial mean influence proportional to its valid observation count when combining unequal data groups.
A one-record chunk must not count as much as a hundred-record chunk when calculating the overall mean.
Windows-1252
Windows-1252 is a legacy single-byte encoding with Western letters and extra symbols that differs from Latin-1 in part of its range.
The byte for the euro sign in Windows-1252 becomes a control character under a Latin-1 interpretation.
Workbook
A workbook is a spreadsheet file containing one or more worksheets along with cell values, types, formulas and presentation details.
A single .xlsx workbook can contain separate sheets for observations, totals and a report summary.
Worksheet
A worksheet is one named grid of cells within a workbook, selected in pandas by its sheet name or zero-based position.
Using sheet_name=1 reads the second worksheet, which may differ from the sheet open on screen.
Write verification
Write verification checks stored database results against the intended change, such as the expected row-count increase after an append.
After adding six rows to a table of 20, query the count and check for the expected total of 26.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started