Problems: Python Basics#
Get this problem set
Download everything (Topic1.1-Python_Basics_Problems.zip) — the notebook and
water_properties.csv, in a folder that is ready to run as-is.
The Download badge at the top of the page will also give you the notebook on its own. On Vocareum everything is already set up for you.
This is the first problem set of the course, so it does two jobs: it gets you started with Python and data files, and it shows you how every later problem set will be arranged.
How these problem sets work
Every set is worth 100 points and has the same three parts.
Part A — Skill Checks (30 pts). Short questions with one right answer. You assign your answer to a named variable, then run a check cell that tells you immediately whether it is accepted. You may resubmit as often as you like, so there is no reason to hand in a Part A that does not pass. The check cells look like this:
grader.check("q1")
Part B — Visualization (35 pts). Make a plot and say what it shows. Graded by your peers against a rubric, so there is usually more than one acceptable answer — but the rubric is specific about what has to be there.
Part C — Open Ended (35 pts). A question with no single right answer, where you are graded on the reasoning and on whether your conclusions follow from what you actually computed. Also peer graded.
The parts build on each other. Part A works out the syntax you need for Part B, and Part B produces the evidence you argue from in Part C, so do them in order.
Cells marked # YOUR CODE HERE are yours to fill in. Everything else is provided and
should run as-is.
One convention worth knowing before you start: a line like n_rows = ... is a placeholder.
The three dots are real Python — an object called Ellipsis that does nothing — and they
mark the spot where your answer goes. Replace the ..., do not add to it. If you run the
check cell without replacing it, the autograder will tell you the question is unanswered
rather than marking it wrong.
Setup#
The dataset is data/water_properties.csv: four thermophysical properties of liquid
water, tabulated every 2 °C from the freezing point to the boiling point at 1 bar. It
comes from the NIST Chemistry WebBook, which serves the IAPWS-95 formulation — the
international standard for the properties of water.
Water is worth starting with because you already know roughly how it behaves, so when the code gives you a number you can tell whether it is sensible. That is a habit worth forming now: the first question to ask of any computed result is whether it could possibly be right.
import numpy as np
import pandas as pd
df = pd.read_csv('data/water_properties.csv')
df.head(10)
| temperature [C] | density [kg/m^3] | Cp [J/g/K] | viscosity [Pa*s] | thermal conductivity [W/m/K] | |
|---|---|---|---|---|---|
| 0 | 0.01 | 999.84 | 4.2194 | 0.001791 | 0.55567 |
| 1 | 2.01 | 999.94 | 4.2130 | 0.001673 | 0.56069 |
| 2 | 4.01 | 999.97 | 4.2075 | 0.001567 | 0.56549 |
| 3 | 6.01 | 999.94 | 4.2027 | 0.001471 | 0.57010 |
| 4 | 8.01 | 999.85 | 4.1987 | 0.001384 | 0.57453 |
| 5 | 10.01 | 999.70 | 4.1951 | 0.001306 | 0.57880 |
| 6 | 12.01 | 999.50 | 4.1921 | 0.001234 | 0.58291 |
| 7 | 14.01 | 999.25 | 4.1896 | 0.001168 | 0.58688 |
| 8 | 16.01 | 998.94 | 4.1874 | 0.001108 | 0.59072 |
| 9 | 18.01 | 998.60 | 4.1856 | 0.001052 | 0.59444 |
import numpy as np loads a library and gives it a short nickname, so every function from
it is written np.something — this is why NumPy calls all look alike. pd.read_csv reads
a comma-separated file into a DataFrame, a table that remembers its column names.
df.head(10) shows the first ten rows, which is always worth doing before anything else:
it is how you find out that the file is what you thought it was.
As in the chapter, .values converts the table into a NumPy array, and columns are
selected by slicing:
X = df.values
print(X.shape)
print(df.columns.values) # which column is which
(51, 5)
['temperature [C]' 'density [kg/m^3]' 'Cp [J/g/K]' 'viscosity [Pa*s]'
'thermal conductivity [W/m/K]']
The five columns are, in order: temperature (°C), density (kg/m³), heat capacity \(C_p\) (J/g/K), viscosity (Pa·s), and thermal conductivity (W/m/K).
Reading NumPy indexing
An array is indexed X[row, column], in that order, and counting starts at zero. So
the first column is X[:, 0] and the second is X[:, 1] — which is why density, the
second column in the file, is index 1. Off-by-one errors here are the single most common
mistake in this problem set.
The colon means “everything along this axis”, so:
X[:, 1]is all rows, column 1 — a whole column.X[10, :]is row 10, all columns — a whole row.X[10, 3]is one single number, the value at row 10 and column 3.
Negative indices count backwards from the end, so X[-1, 0] is the last temperature in the
table without your needing to know how many rows there are.
To print a number readably, use an f-string: putting f in front of a string lets you drop
a variable into it inside braces, and :.4f after the name rounds it to four decimals.
print(f"mean density = {mean_density:.4f} kg/m^3")
Run this once to load the autograder. It will not run inside the book — use the downloaded notebook.
import otter
grader = otter.Notebook()
Part A — Skill Checks (30 pts)#
Three questions, 10 points each. Each asks for a single number.
A1. Load the data and measure it (10 pts)#
Exercise 137
Using the array X created above, find how many rows the dataset has — that is, how many
temperatures are tabulated.
X.shape returns the array’s dimensions as (rows, columns), so the number of rows is
its first element.
Assign the number of rows to n_rows.
# YOUR CODE HERE
n_rows = ...
grader.check("q1")
A2. Average a column (10 pts)#
Exercise 138
Compute the mean density over all the tabulated temperatures, using np.mean.
Density is the second column, which is index 1, so X[:, 1] selects it — every row, column
one.
Assign the result to mean_density. The units are kg/m³.
# YOUR CODE HERE
mean_density = ...
grader.check("q2")
A3. Convert units and check against something you know (10 pts)#
Exercise 139
Viscosity is the fourth column (index 3), and NIST reports it in Pa·s. Chemical engineers more often quote the centipoise, where 1 Pa·s = 1000 cP.
Row index 10 of the table is 20.01 °C. Take the viscosity there and convert it to centipoise.
Assign the result to viscosity_cP.
# YOUR CODE HERE
viscosity_cP = ...
grader.check("q3")
Part B — Visualization (35 pts)#
This is where matplotlib gets introduced properly. The chapter’s pattern is:
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x, y, marker='o', ls='none')
ax.set_xlabel('...')
ax.set_ylabel('...')
plt.subplots makes two things at once and hands them back together: a figure (fig), the
canvas as a whole, and an axes (ax), the panel with the data on it. Everything after that
is a method — a function that belongs to ax and is called by writing a dot after it, in
the same way df.head() belonged to the DataFrame. So ax.plot draws on that panel and
ax.set_xlabel labels it, and if you had two panels each would take its own commands.
Axis limits work the same way, through ax.set_xlim and ax.set_ylim.
marker='o', ls='none' is how you get points with no connecting line. Arguments passed by
name like this can be given in any order, and any you leave out fall back to a default.
Exercise 140
Viscosity against temperature. Plot column 3 against column 0, with points rather than a connecting line. Label both axes, including units.
Thermal conductivity against temperature. The same again for column 4, as a second figure.
Zoom in. Redraw the viscosity plot restricted to 0–40 °C using
ax.set_xlim, and choose aax.set_ylimthat makes that range fill the axes.In 3–4 sentences, describe the two curves. Is either one a straight line? Which changes more over the range, and roughly by what factor? Read the factor off your own plot rather than computing it — Part C will do the arithmetic.
An unlabeled axis is the most common way to lose points on a plot, in this course and afterwards. Units belong on both axes of every figure you make from here on.
# YOUR CODE HERE
fig, ax = plt.subplots(figsize=(10, 5))
Part C — Open Ended (35 pts)#
This part asks you to write your first function and your first loop, so here is the shape of each.
A function is defined with def, takes whatever you list in the parentheses, and hands a
value back with return. The indented block underneath is the body — indentation is how
Python knows where a block starts and stops, so it is not optional. A string on the first
line of the body is the docstring, which is where you say what the function does.
def double(x):
"""Return twice x."""
return 2 * x
A for loop repeats the indented block once for each item in a list, with the loop
variable taking each value in turn. zip pairs up two lists so you can walk through both
at once — useful when each column index has a name you want to print alongside it.
for j, name in zip([1, 2], ['density', 'Cp']):
print(j, name)
Exercise 141
Part B suggested that water’s properties are not equally sensitive to temperature. Settle it for all four.
Write a function. Define a function that takes a column index and returns the fractional change in that column from the first row to the last:
\[ \text{fractional change} \;=\; \frac{v_\text{last} - v_\text{first}}{v_\text{first}} \]Give it a docstring saying what it does.
X[0, j]is the first row of columnjandX[-1, j]is the last.Apply it to all four property columns (1 through 4) and report the results as percentages. A
forloop over the column indices is the natural way;zipis useful if you want to pair each index with a name.Plot all four together. Divide each property column by its own value in the first row, so every curve starts at 1, and plot all four against temperature on one set of axes. Curves on one axes need a legend: pass
label='...'to eachax.plotcall and then callax.legend().One paragraph. Which property is most sensitive to temperature, and by how much? Pick one of these and say what your numbers imply for it:
pumping the water through a pipe, where pressure drop rises with viscosity;
heating it in a heat exchanger, where the heat needed depends on \(C_p\);
and say whether treating that property as constant over 0–100 °C would be reasonable.
You are not expected to know heat exchanger design. A sensible argument from your own numbers is the whole requirement.
# YOUR CODE HERE
Summary#
Part A loaded a real dataset, measured its size, averaged a column and converted units — and every answer was checkable against something already known about water, which is how you catch mistakes before they propagate.
Part B introduced
matplotlibthrough the chapter’s pattern:plt.subplotsto make a figure and axes,ax.plotto draw,ax.set_xlabelandax.set_ylabelto label, andax.set_xlim/ax.set_ylimto zoom.Part C turned an impression from a plot into numbers by writing a function and looping over the columns, and found that water’s viscosity changes by 84% over the liquid range while its heat capacity changes by almost nothing.
Additional Reading#
NIST Chemistry WebBook, Thermophysical Properties of Fluid Systems — the source of this dataset, and a useful reference throughout the course.
The matplotlib gallery — worked examples with source code, the fastest way to find out how to draw something.