Working With Data in Python
1. A variable is a measurement with its unit written down
A variable holds one number. A comment, everything after a #, holds what that number means. Python ignores the comment. Your future self does not, and neither does anyone reading your analysis.
length = 1.20# meters, the length of the track
Two students both write L = 1.20 and one of them adds the unit in a comment. Both lines run perfectly. A month later only one of them still knows whether that was meters, centimeters or feet, and the other one has a number that cannot be used for anything.
Python distinguishes a whole number, an int, from a decimal, a float. Almost every measurement is a float. Counts of things are ints.
2. Arrays, because a run is not one number
One measurement fits in a variable. A three-second run at 20 Hz is sixty-one of them. NumPy gives you an array, which holds the whole column and lets you operate on all of it at once.
times * 2doubles every element, with no loop
Square brackets pick elements out. Counting starts at zero, so x[0] is the first value and x[1] is the second. x[-1] is the last one, whatever the length turns out to be, which is the habit worth forming: it does not go stale when tomorrow’s run is longer.
np.sum, np.mean, np.max and np.min each take a whole array and hand back a single number.
3. Reading a Capstone file, and the trap in it
A PASCO Capstone export does not begin with the column names. Its first line is the run title. If you load it without saying so, pandas treats Cart on a Ramp – Run 1 as the header, every column name comes out wrong, and every number becomes text.
data = pd.read_csv(“capstone_cart_run1.csv”, skiprows=1)
That is the dangerous kind of error, because nothing turns red. The code runs, you get a table, and it is garbage. The check is to print the column names immediately after loading and look at them.
What does this error mean?
The last line of a real Python error message. Pick what actually went wrong. These are the four errors you will meet, and meeting them here is better than meeting them five minutes before a deadline.
4. The first real analysis, and its check
Average velocity over a run is the change in position divided by the change in time. With the columns pulled out as arrays, that is three lines.
v_avg = (x[-1] – x[0]) / (t[-1] – t[0])
For the class run that gives 0.6301 m/s. Now do the part that matters: the cart sped up the whole way, so its average velocity has to lie between its starting and its ending velocity. Those are −0.0028 and 1.2565 m/s, and 0.6301 sits between them. The number survives.
5. Plots, and the rule about axes
One plot is worth a column of numbers. Do not worry about styling. Do worry about labels: every axis gets the quantity and its unit, every time, starting now, while the habit is cheap to form.
Plot position against time for the cart run and you get a curve that bends upward. Plot velocity against time and you get something very close to a straight line. That contrast is the whole result: a straight velocity graph means a constant acceleration, and the bend in the position graph is what a constant acceleration looks like one level up.
Check yourself
1. You run a cell and get NameError: name ‘v_avg’ is not defined, but you can see v_avg being defined three cells above. What happened?
You did not run that cell, or you ran it before restarting the session. A notebook remembers what has actually been executed, not what is written on the page. The fix is to run the earlier cell, or to choose Runtime and then Restart session and run all, which is the honest test that your notebook works from a cold start.
2. You load the Capstone file without skiprows=1. No error appears. Name two things you would notice if you looked, and say why this is worse than a crash.
The column names would come out as the run title and Unnamed: 1 and Unnamed: 2, and the row count would be one too many. It is worse than a crash because a crash stops you. This carries on and gives you numbers, and they are text rather than numbers, so any average you compute from them is either an error much later or a silent nonsense.
3. The run was described as 20 Hz. Do not take that on trust. Say how you would check it from the data itself, and what you would expect.
Compute t[1] – t[0], which should be 0.05 s, and then 1 / 0.05 = 20 samples per second. Better still, check that the spacing is the same all the way through rather than only at the start, since a dropped sample would not show up in the first pair. This is the general move: anything you were told about the data can be recovered from the data, and should be.
4. Why is x[-1] a better habit than x[60], even though both give the last value for this run?
Because x[-1] means the last one and stays correct when you take a longer run tomorrow, while x[60] means position sixty and silently becomes the wrong element, or an IndexError, the moment the length changes. Code that encodes a fact about today’s file is code that breaks on the next file.
Practice 2, Plots, Slices and Fits. You have an average over the whole run. The next step is asking what happened during it: taking slices, fitting a line to the velocity, and turning the slope into an acceleration with an uncertainty attached.