{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Processing Text Data\n", "\n", "## Overview, Objectives, and Key Terms\n", " \n", "Lectures [5](A01_Algorithms_Flowcharts_and_Pseudocode.ipynb) through [9](A06_Pythonic_Containers.ipynb) covered the basic logical structures used in programming and their implementation in Python. [Lecture 10](A06_Pythonic_Containers.ipynb) presented Python's built-in container types. In this lecture, we turn to the practical problem of processing text data. Often, such data starts life in *files* on our machines. Ultimately, that data is represented as one (or more) strings that can be processed using a combination of the structures already covered (particularly, loops) and more specialized string functions. We'll wrap up with ways in which we can output existing data into useful text-based formats.\n", " \n", "### Objectives\n", "\n", "By the end of this lesson, you should be able to\n", "\n", "- Open and process text files.\n", "- Use string functions to parse data into desired formats.\n", "- Convert data into desired string formats.\n", "- Write strings to text files\n", "\n", "### Key Terms\n", "\n", "- `open`\n", "- `close`\n", "- `read`\n", "- `str`\n", "- `str.split`\n", "- `str.count`\n", "- `str.find`\n", "- `str.isnumeric`\n", "- `str.replace`\n", "- `in` operator\n", "- `str.format`\n", "- `{}` for replacement\n", "- `write`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reading Text Files\n", "\n", "We'll start with a case we've seen before: the text file from [Lecture 4](L04_MoreOnNumPyArrays.ipynb), the contents of which are \n", "\n", "```\n", "time (s) vel (m/s) acc (m/s**2)\n", "0.00000000 1.00000000 0.00000000\n", "0.22222222 1.24884887 0.01097394\n", "0.44444444 1.55962350 0.08779150\n", "0.66666667 1.94773404 0.29629630\n", "0.88888889 2.43242545 0.70233196\n", "1.11111111 3.03773178 1.37174211\n", "1.33333333 3.79366789 2.37037037\n", "1.55555556 4.73771786 3.76406036\n", "1.77777778 5.91669359 5.61865569\n", "2.00000000 7.38905610 8.00000000\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It was suggested then that any data with such a simple format is best read by using `np.loadtxt`. However, the simplicity of this data makes it useful for studying more traditional file processing.\n", "\n", "In Python, files are first opened to produce a *file handle*, i.e., a variable that provides the user access to the file and various functions with which to inspect the file. To load a file and produce such a file handle requires the built-in `open` function. This function is typically called with two arguments: a filename, always a `str` value, and the access mode, which can be `r` for *read*, `w` for *write*, and `a` for *append*. For now, we'll focus on reading files, and we can open `data.txt` for reading by executing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('data.txt', 'r')\n", "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The particular value of `f` is not important, but it does suggest it is associated with our text file and that it is set for reading. At this point, though, the file is only *ready* to be processed; we still need to do something with it. Let's see what we can do with the file handle `f`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for item in dir(f): \n", " if not item[0:1] == '_':\n", " print(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In fact, file handles have quite a few functions. The important ones for getting the content of the file into our program are `read` and `readlines`. We'll explore `write` later on. Let's start with `f.read()`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "help(f.read)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "By default, `read` will read *all* the characters. Although not stated, the function produces a `str` with all of the characters read. Hence, we can turn the contents of our text file (connected now to `f`) into a single string via" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = f.read()\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Well, the contents sure are there, but the formatting is a bit weird. If we *print* the string, we see what we might expect:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, displaying a `str` variable (and not printing it) will show all of the characters, including the special `\\n` character. Here, `\\n` is a *newline* character and represents the break between lines in text files. When a string is printed, the effects of special characters (like `\\n`) are shown.\n", "\n", "> **Exercise**: Define a string that, when printed, shows \"ABC\" on the first line and \"XYZ\" on the second line.\n", "\n", "Now that we've read the file into a single string, we need to close it:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is important to close files once read. Doing so helps to prevent multiple programs from accessing the same file. \n", "\n", "> **Note**: Always close a file once it has been read.\n", "\n", "\n", "