{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"LSE Data Science Institute | DS105A (2023/24) | Week 04\n",
"\n",
"# 🗓️ Week 04 – Data types, File formats, and live coding\n",
"\n",
"Theme: Behind the scenes\n",
"\n",
"**DATE:** 19 October 2023\n",
"\n",
"**AUTHOR:** [@jonjoncardoso](https://jonjoncardoso.github.io)\n",
"\n",
"------------------------------\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ⚙️ Setup\n",
"\n",
"Let's start by importing the libraries we will use today:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"💡 We can run **Terminal** comands inside Jupyter notebook!!!! All you need to do is to add a `!` before the command. The code will no longer be interpreted as Python code, but as a Terminal command.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!ls -lh"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!cd data && ls -lh"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But be careful! Even if you `cd`, you will not change the directory of the notebook. The `pwd` will always remain the same:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pwd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. We need good datasets\n",
"\n",
"\n",
"> 📒 A **dataset** is simply a collection of data.\n",
"\n",
"- But just having a collection of data is not enough...\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### We need organised datasets \n",
"\n",
"Otherwise, we won't be at our most productive in subsequent stages of the data science workflow. \n",
"\n",
"Soon, you will start collecting data. You will notice first-hand how messy data can be."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🌐 Click [here](https://opendata.camden.gov.uk/Crime-and-Criminal-Justice/On-Street-Crime-In-Camden-Map/893b-tp33) to view the **Open Street Crime Map** data for Camden, London. We will use this resource as an example to explore different file formats."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## File format: CSV\n",
"\n",
"Let's start by exporting the crime data as a CSV file.\n",
"\n",
"Place the downloaded file in the `./data` folder of your project (create this folder if it doesn't exist yet)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**We downloaded a CSV file. The [pandas documentation](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas-read-csv) suggests we can use the `read_csv()` function to read it:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime = pd.read_csv(\"./data/On_Street_Crime_In_Camden_Map.csv\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🗣️ **CLASSROOM DISCUSSION:** What does the message above mean? Is it an error? How can I know?\n",
"\n",
"Click here to see a possible answer
\n",
"\n",
"To understand the error above, we need to understand the concept of `dtype` (data type). When reading the file, the 🐼 pandas library tries to infer a lot of things about the data. \n",
"\n",
"Since the file ends with `.csv`, a **structured data format**, 🐼 pandas assumes a few things:\n",
"\n",
"1. this is a **C**omma-**S**eparated **V**alues file, which is a fancy way to say that the data is separated by commas (`,`).\n",
"\n",
"2. on top of the commas, the data is also separated by **new lines** (`\\n`)\n",
"\n",
"3. each line represents a **row** of data, an individual **observation**\n",
"\n",
"4. the very first row is special. It contains the **column names**. Each column name is separated by, again, a comma (`,`)\n",
"\n",
"5. _the data in each column is of the same **type**._\n",
"\n",
"💡 The message above is not an Error, but a Warning and it seems connected with Assumption 5. 🐼 pandas is trying to infer the data type of each column, it fails to do so but it still manages to read the file.\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can confirm that the file was read by checking out the first 5 rows of the data:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**How do I get a list of column names**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime.columns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Do you want to know how many columns are there? Use the function `len()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"len(df_street_crime.columns)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**What if I just want to see a few columns?**\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"selected_columns = [\"Category\", \"Street ID\", \"Street Name\", \"Outcome Category\", \"Outcome Date\", \"Location\"]\n",
"\n",
"# Save to illustrate how CSV looks like in raw format\n",
"df_street_crime[selected_columns].head(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Let's save this reduced dataset as a CSV file**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime[selected_columns].to_csv(\"./data/reduced_crime_data.csv\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What does the dataset looks like in its true form? (Not when read by Pandas)\n",
"\n",
"Let's use the `head` command to see the first 5 lines of the file:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!head ./data/reduced_crime_data.csv"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data Types"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also get more info about what is stored in the `df_street_crime` variable by using the `info()` method:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime.info()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🗣️ **CLASSROOM DISCUSSION:** What part of the message above is related to the types of data stored in each column? And what does it mean?\n",
"\n",
"Click here to read a possible answer
\n",
"\n",
"The `Dtype` column shows the data type of each column.\n",
"\n",
"What is funny about the above is that pretty much all columns are of type `object`. This is 🐼 pandas way of saying \"I don't know what data type this column is, I will treat it as text\".\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Data Type: Integer\n",
"\n",
"An integer is a whole number (not a fraction) that can be positive, negative, or zero.\n",
"\n",
"At a lower level, at the computer's memory, an integer is represented by a **limited** sequence of bits (zeros and ones). I say limited because the number of bits used to represent an integer is fixed. See the `int64` notation under the 'Street ID' column? This means that the computer is using **64 individual bits** to represent each integer in that column.\n",
"\n",
"\n",
"Click here to see how Integers work
\n",
"\n",
"\n",
"Suppose we only had 8 bits to represent an integer. The drawing below represents a single number, encoded in eight rectangular boxes. Each box represents a bit and they are colored in red if they have the number 1 and light grey if 0:\n",
"\n",
"\n",
" \n",
" 1\n",
" \n",
" \n",
" 1\n",
" \n",
" \n",
" 0\n",
" \n",
" \n",
" 0\n",
" \n",
" \n",
" 0\n",
" \n",
" \n",
" 0\n",
" \n",
" \n",
" 1\n",
" \n",
" \n",
" 0\n",
" \n",
"\n",
"\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Let's check a single column: 'Street ID'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What are all the different integer sizes supported?\n",
"\n",
"- We would have to look at [numpy's documentation on Integer types](https://numpy.org/doc/stable/reference/arrays.scalars.html#integer-types). Pandas uses numpy under the hood to store data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**What would be the most adequate integer type for the `Street ID` column?**\n",
"\n",
"Click here to read spoilers
\n",
"\n",
"- Check the min and max of the column with the code:\n",
"\n",
" ```python\n",
" df_street_crime[''].min()\n",
" ```\n",
" \n",
" ```python\n",
" df_street_crime[''].max()\n",
" ```\n",
"\n",
"- Learn how to convert a pandas column to a different data type using [.astype()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html)\n",
"\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"🗣️ **What do you think would happen if I tried to conver this column to `np.int8` instead??**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Data Type: [Floating Point types](https://numpy.org/doc/stable/reference/arrays.scalars.html#floating-point-types)\n",
"\n",
"💡 Tip: '[Why is my addition/multiplication not working??](https://stackoverflow.com/a/52931828/843365)'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime['Easting']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Data Type: [Text/strings(object)](https://pandas.pydata.org/pandas-docs/stable/user_guide/text.html)\n",
"\n",
"Without getting into the specifics of how 🐼 pandas represents text, it is important that you learn about encodings!\n",
"\n",
"That is because, text is of course also represented as a sequence of bits. But how do we know which sequence of bits represents which character?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### ASCII table\n",
"\n",
"- The ASCII table is one of early standards\n",
"- It encodes **characters** using 7-bits. Therefore, it can represent a total of 128 unique characters\n",
"\n",
"Here is a snippet of the ASCII table:\n",
"\n",
" Click here to see Part I of the ASCII table
\n",
"\n",
"| Dec | Binary | Char | Description |\n",
"|------:|---------:|:-------|:--------------------------|\n",
"| 0 | 0000000 | NUL | Null |\n",
"| 1 | 0000001 | SOH | Start of Header |\n",
"| 2 | 0000010 | STX | Start of Text |\n",
"| 3 | 0000011 | ETX | End of Text |\n",
"| 4 | 0000100 | EOT | End of Transmission |\n",
"| 5 | 0000101 | ENQ | Enquiry |\n",
"| 6 | 0000110 | ACK | Acknowledge |\n",
"| 7 | 0000111 | BEL | Bell |\n",
"| 8 | 0001000 | BS | Backspace |\n",
"| 9 | 0001001 | HT | Horizontal Tab |\n",
"| 10 | 0001010 | LF | Line Feed |\n",
"| 11 | 0001011 | VT | Vertical Tab |\n",
"| 12 | 0001100 | FF | Form Feed |\n",
"| 13 | 0001101 | CR | Carriage Return |\n",
"| 14 | 0001110 | SO | Shift Out |\n",
"| 15 | 0001111 | SI | Shift In |\n",
"| 16 | 0010000 | DLE | Data Link Escape |\n",
"| 17 | 0010001 | DC1 | Device Control 1 |\n",
"| 18 | 0010010 | DC2 | Device Control 2 |\n",
"| 19 | 0010011 | DC3 | Device Control 3 |\n",
"| 20 | 0010100 | DC4 | Device Control 4 |\n",
"| 21 | 0010101 | NAK | Negative Acknowledge |\n",
"| 22 | 0010110 | SYN | Synchronize |\n",
"| 23 | 0010111 | ETB | End of Transmission Block |\n",
"| 24 | 0011000 | CAN | Cancel |\n",
"| 25 | 0011001 | EM | End of Medium |\n",
"| 26 | 0011010 | SUB | Substitute |\n",
"| 27 | 0011011 | ESC | Escape |\n",
"| 28 | 0011100 | FS | File Separator |\n",
"| 29 | 0011101 | GS | Group Separator |\n",
"| 30 | 0011110 | RS | Record Separator |\n",
"| 31 | 0011111 | US | Unit Separator |\n",
"\n",
"\n",
" \n",
"\n",
"
\n",
"\n",
" Click here to see Part II of the ASCII table
\n",
"\n",
"| Dec | Binary | Char | Description |\n",
"|------:|---------:|:-------|:------------------|\n",
"| 32 | 0100000 | space | Space |\n",
"| 33 | 0100001 | ! | exclamation mark |\n",
"| 34 | 0100010 | \" | double quote |\n",
"| 35 | 0100011 | # | number |\n",
"| 36 | 0100100 | $ | dollar |\n",
"| 37 | 0100101 | % | percent |\n",
"| 38 | 0100110 | & | ampersand |\n",
"| 39 | 0100111 | ' | single quote |\n",
"| 40 | 0101000 | ( | left parenthesis |\n",
"| 41 | 0101001 | ) | right parenthesis |\n",
"| 42 | 0101010 | * | asterisk |\n",
"| 43 | 0101011 | + | plus |\n",
"| 44 | 0101100 | , | comma |\n",
"| 45 | 0101101 | - | minus |\n",
"| 46 | 0101110 | . | period |\n",
"| 47 | 0101111 | / | slash |\n",
"| 48 | 0110000 | 0 | zero |\n",
"| 49 | 0110001 | 1 | one |\n",
"| 50 | 0110010 | 2 | two |\n",
"| 51 | 0110011 | 3 | three |\n",
"| 52 | 0110100 | 4 | four |\n",
"| 53 | 0110101 | 5 | five |\n",
"| 54 | 0110110 | 6 | six |\n",
"| 55 | 0110111 | 7 | seven |\n",
"| 56 | 0111000 | 8 | eight |\n",
"| 57 | 0111001 | 9 | nine |\n",
"| 58 | 0111010 | : | colon |\n",
"| 59 | 0111011 | ; | semicolon |\n",
"| 60 | 0111100 | < | less than |\n",
"| 61 | 0111101 | = | equality sign |\n",
"| 62 | 0111110 | > | greater than |\n",
"| 63 | 0111111 | ? | question mark |\n",
"\n",
" \n",
"\n",
"Click [here](https://www.ascii-code.com/) to see the full thing.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Other encoding standards\n",
"\n",
"ASCII is not the only standard. There are other ways to encode text using binary.\n",
"\n",
"Below is a non-comprehensive list of other text (**encoding**):\n",
"\n",
"- Unicode\n",
"- UTF-8 (Most common of all)\n",
"- UTF-16\n",
"- UTF-32\n",
"- ISO-8859-1\n",
"- Latin-1\n",
"\n",
"🔗 [Here](https://docs.python.org/3/library/codecs.html#standard-encodings) is the full list of encoding standards supported by Python by default.\n",
"\n",
"\n",
"💡 You might have come across encoding mismatches before if you ever opened a file and the text looked like this:\n",
"\n",
"> \"Nestlé and Mötley Crüe\"\n",
"\n",
"Where it should have read \n",
"\n",
"> \"Nestlé and Mötley Crüe\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Emojis are text 😃 !\n",
"\n",
"See the complete list on the [Unicode website](https://unicode.org/emoji/charts/full-emoji-list.html)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#As far as I know, this CSV file is free of non-standard characters, \n",
"# so changing the encoding to something else should not change much.\n",
"# After all, most standards are supersets of ASCII.\n",
"pd.read_csv(\"./data/On_Street_Crime_In_Camden_Map.csv\", encoding=\"ascii\", encoding_errors=\"strict\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Data type: [Categorical](https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html)\n",
"\n",
"Click here to read spoilers
\n",
"\n",
"- How to show what is inside a column\n",
"- How to show just the unique values of a column (`df['']unique()`)\n",
"- Count the number of unique values in a column (`df[''].nunique()`)\n",
"- Count the number of times each unique value appears in a column (`df[''].value_counts()`)\n",
"\n",
"Hidden pro-tip
\n",
"\n",
"Here is how you can create a plot showing the percentage of each unique value in a column:\n",
"\n",
"```python\n",
"df_street_crime['Category'].value_counts(normalize=True).apply(lambda x: x*100).plot(kind='bar')\n",
"```\n",
"\n",
" \n",
"\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime['Category']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Converting to a Categorical data type.**\n",
"\n",
"When data is clearly categorical (the hint for this one is in the name of the column), we can convert it to a Categorical data type. This might also make our life easier when we want to do some analysis on this column.\n",
"\n",
"Here are the reasons the 🐼 pandas documentation on [Categorical Data](https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html) says you should use it:\n",
"\n",
"> The categorical data type is useful in the following cases:\n",
">\n",
"> - A string variable consisting of only a few different values. Converting such a string variable to a categorical variable will save some memory, see here.\n",
">\n",
"> - The lexical order of a variable is not the same as the logical order (“one”, “two”, “three”). By converting to a categorical and specifying an order on the categories, sorting and min/max will use the logical order instead of the lexical order, see here.\n",
">\n",
"> - As a signal to other Python libraries that this column should be treated as a categorical variable (e.g. to use suitable statistical methods or plot types).\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime['Category'] = pd.Categorical(df_street_crime['Category'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_street_crime.info()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Show that we can convert the `datetime` column to a `datetime` object:\n",
"df[\"Outcome Date\"] = pd.to_datetime(df[\"Outcome Date\"])\n",
"\n",
"# Make `Outcome Category` a categorical column\n",
"df[\"Outcome Category\"] = df[\"Outcome Category\"].astype(\"category\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[\"Outcome Category\"].cat.categories"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.dtypes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[\"Outcome Date\"].dt.day_name()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_as_list = df.astype(str).values.tolist()\n",
"\n",
"with open(\"data/sample.txt\", \"w\") as f:\n",
" f.write(\"[\")\n",
" for item_list in df_as_list:\n",
" f.write(\"[\")\n",
" f.write(\"','\".join(item_list))\n",
" f.write(\"'],\\n\")\n",
" f.write(\"]\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## File format: JSON\n",
"\n",
"Say we download the JSON version of the data. How should we read it as a Data Frame?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"filepath = Path(\"./data/rows.json\")\n",
"\n",
"df = pd.read_json(filepath)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The path is correct but pandas could not parse things correctly. \n",
"\n",
"We have to find a workaround:\n",
"\n",
"👉 read the JSON file as a Python dictionary using the `json` library instead"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"with open(\"data/rows.json\", \"r\") as read_file:\n",
" data = json.load(read_file)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check the data type of the variable `data`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"type(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"How many keys are there in the dictionary?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"len(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What are the keys?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data.keys()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Conclusion: the data is the same but it is structured in a completely different way."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The actual data is in the `data` key\n",
"len(data[\"data\"])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Here is how we could convert it to a DataFrame\n",
"pd.DataFrame(data[\"data\"]).head(12)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Where did the column names go???\n",
"\n",
"Read spoilers here
\n",
"\n",
"After much trial and error, I found out that the column names are stored in the `meta` key of the dictionary. But I have to go deeper:\n",
"\n",
"```python\n",
"data[\"meta\"][\"view\"][\"columns\"]\n",
"```\n",
"\n",
" \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Is there a way to **normalise** this data?\n",
"\n",
"Normalise = flatten the data structure\n",
"\n",
"Read spoilers here
\n",
"\n",
"```python\n",
"df_columns = pd.io.json.json_normalize(data[\"meta\"][\"view\"][\"columns\"])\n",
"df_columns.head(6)\n",
"```\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Putting it all together:\n",
"\n",
"See solution
\n",
"\n",
"```python\n",
"column_names = df_columns[\"name\"].tolist()\n",
"\n",
"df_crime = pd.DataFrame(data[\"data\"], columns=column_names)\n",
"\n",
"selected_columns = [\"Category\", \"Street ID\", \"Street Name\", \"Outcome Category\", \"Outcome Date\", \"Location\"]\n",
"\n",
"print(df_crime[selected_columns].head().to_markdown(index=False))\n",
"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"column_names = df_columns[\"name\"].tolist()\n",
"\n",
"df_crime = pd.DataFrame(data[\"data\"], columns=column_names)\n",
"\n",
"selected_columns = [\"Category\", \"Street ID\", \"Street Name\", \"Outcome Category\", \"Outcome Date\", \"Location\"]\n",
"\n",
"print(df_crime[selected_columns].head().to_markdown(index=False))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are back to where we were with the CSV file!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python tricks\n",
"\n",
"I will construct this section with you during the lecture.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.8"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "86a4f56bb4e17d4e79f8e80b0f18a6d84d252069e5d9eb74ea21d8503d143f4e"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}