{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Reshaping Data\n",
"\n",
"This notebook discusses operations to *reshape* data:\n",
"\n",
"1. Collapsing rows through aggregates\n",
"2. Joining data frames together (basic joins)\n",
"3. Pivoting between wide and long formats\n",
"\n",
"The [Selection](Selection.ipynb) notebook discussed how to select subsets of rows or columns; these operations will change what the rows and columns are, or add new items.\n",
"\n",
"This notebook uses the “MovieLens + IMDB/RottenTomatoes” data from the [HETREC data](https://grouplens.org/datasets/hetrec-2011/)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"First we will import our modules:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then import the HETREC MovieLens data. A few notes:\n",
"\n",
"- Tab-separated data\n",
"- Not UTF-8 - latin-1 encoding seems to work\n",
"- Missing data encoded as `\\N` (there's a good chance that what we have is a PostgreSQL data dump!)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Movies"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" userID movieID rating timestamp\n",
"0 75 3 1.0 1162160236000\n",
"1 75 32 4.5 1162160624000\n",
"2 75 110 4.0 1162161008000\n",
"3 75 160 2.0 1162160212000\n",
"4 75 163 4.0 1162160970000"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings = pd.read_csv('hetrec2011-ml/user_ratedmovies-timestamps.dat', delimiter='\\t', encoding='latin1')\n",
"ratings.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Grouping and Aggregating\n",
"\n",
"The group and aggregate operations allow us to collapse multiple rows, that share a common value in one or more columns (the *grouping key*), into a single row.\n",
"There are three pieces of a group-aggregate operation:\n",
"\n",
"- The grouping key — one or more columns that are used to identify which rows are in the same group\n",
"- The column(s) to aggregate\n",
"- The aggregate function(s) to apply\n",
"\n",
"A group/aggregate operation transforms a data frames using thes columns as follows:\n",
"\n",
"- Each *unique combination* of values in the **grouping key** becomes *one row*. If the grouping key is one column, this means each distinct value of the grouping column will yield one row in the final results.\n",
"- The **columns to aggregate** are collapsed into a single value using the specified aggregate function(s).\n",
"- Other columns are ignored and do not appear in the output."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Aggregate to Series\n",
"\n",
"**If we have:** a data frame \n",
"**And we have:** a column identifying each observation's group membership \n",
"**And we want:** a series with an entry for each group, whose value is an aggregate function of another column \n",
"**Then we can:** use `groupby` with one column and the aggregate function.\n",
"\n",
"For example, if we want to find the timestamp of the first rating for each movie, we can group the ratings table by `movieID` and take the `min` of the `timestamp` column:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"movieID\n",
"1 876894948000\n",
"2 891835167000\n",
"3 931525286000\n",
"4 951680805000\n",
"5 874593700000\n",
" ... \n",
"65088 1230851753000\n",
"65091 1230918649000\n",
"65126 1231028759000\n",
"65130 1231061731000\n",
"65133 1231034528000\n",
"Name: timestamp, Length: 10109, dtype: int64"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings.groupby('movieID')['timestamp'].min()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This breaks down into a few pieces. The `groupby` method returns a group-by object:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings.groupby('movieID')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `DataFrameGroupBy` is a iterable over `(key, df)` tuples, where `key` is a single value of the grouping key, and `df` is a data frame containing the group's data (the `next` function gets the next value of an iterable):"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1,\n",
" userID movieID rating timestamp\n",
" 556 170 1 3.0 1162208198000\n",
" 639 175 1 4.0 1133674606000\n",
" 915 190 1 4.5 1057778398000\n",
" 1211 267 1 2.5 1084284499000\n",
" 1643 325 1 4.0 1134939391000\n",
" ... ... ... ... ...\n",
" 850646 71420 1 5.0 948256089000\n",
" 852838 71483 1 4.0 1035837220000\n",
" 853507 71497 1 5.0 1188256917000\n",
" 853757 71509 1 4.0 1018636872000\n",
" 855327 71529 1 4.5 1162098801000\n",
" \n",
" [1263 rows x 4 columns])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(iter(ratings.groupby('movieID')))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The column selection yields a `SeriesGroupBy`, which is a group-by for a series instead of a frame:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings.groupby('movieID')['timestamp']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, calling `min` on this will apply the `min` function to each group, and put the results together into a series."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Multiple Aggregates\n",
"\n",
"**If we have:** a data frame \n",
"**And we have:** a column identifying each observation's group membership \n",
"**And we want:** a data frame with an entry for each group, with a column for each of one or more aggregate functions of a column \n",
"**Then we can:** use `groupby` with one column and the `.agg` method with aggregate function names\n",
"\n",
"For example, if we want to find the timestamp of the first rating and last ratings for each movie, we can group the ratings table by `movieID` and take the `min` and `max` of the `timestamp` column:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
min
\n",
"
max
\n",
"
\n",
"
\n",
"
movieID
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
1
\n",
"
876894948000
\n",
"
1231030405000
\n",
"
\n",
"
\n",
"
2
\n",
"
891835167000
\n",
"
1231030891000
\n",
"
\n",
"
\n",
"
3
\n",
"
931525286000
\n",
"
1231099805000
\n",
"
\n",
"
\n",
"
4
\n",
"
951680805000
\n",
"
1229214105000
\n",
"
\n",
"
\n",
"
5
\n",
"
874593700000
\n",
"
1230915209000
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
65088
\n",
"
1230851753000
\n",
"
1230851753000
\n",
"
\n",
"
\n",
"
65091
\n",
"
1230918649000
\n",
"
1230918649000
\n",
"
\n",
"
\n",
"
65126
\n",
"
1231028759000
\n",
"
1231097168000
\n",
"
\n",
"
\n",
"
65130
\n",
"
1231061731000
\n",
"
1231061731000
\n",
"
\n",
"
\n",
"
65133
\n",
"
1231034528000
\n",
"
1231129793000
\n",
"
\n",
" \n",
"
\n",
"
10109 rows × 2 columns
\n",
"
"
],
"text/plain": [
" min max\n",
"movieID \n",
"1 876894948000 1231030405000\n",
"2 891835167000 1231030891000\n",
"3 931525286000 1231099805000\n",
"4 951680805000 1229214105000\n",
"5 874593700000 1230915209000\n",
"... ... ...\n",
"65088 1230851753000 1230851753000\n",
"65091 1230918649000 1230918649000\n",
"65126 1231028759000 1231097168000\n",
"65130 1231061731000 1231061731000\n",
"65133 1231034528000 1231129793000\n",
"\n",
"[10109 rows x 2 columns]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings.groupby('movieID')['timestamp'].agg(['min', 'max'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that in both cases, the resulting frame or series is indexed by the grouping column.\n",
"\n",
"> *Practice: compute the mean and count of the ratings for each movie*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Counting Values\n",
"\n",
"There's a useful special case of grouped aggregation - counting how many times each distinct value in a column appears.\n",
"\n",
"**If we have:** a series \n",
"**And we want:** a series whose index keys are the values of the original series, and whose values are the number of times each value appeared in the original series \n",
"**Then we can:** use the `value_counts` method:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4.0 215773\n",
"3.0 155918\n",
"3.5 150582\n",
"4.5 88652\n",
"5.0 71680\n",
"2.5 62454\n",
"2.0 57188\n",
"1.0 21535\n",
"1.5 18328\n",
"0.5 13488\n",
"Name: rating, dtype: int64"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings['rating'].value_counts()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also sort the results with the `sort_index` method:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.5 13488\n",
"1.0 21535\n",
"1.5 18328\n",
"2.0 57188\n",
"2.5 62454\n",
"3.0 155918\n",
"3.5 150582\n",
"4.0 215773\n",
"4.5 88652\n",
"5.0 71680\n",
"Name: rating, dtype: int64"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratings['rating'].value_counts().sort_index()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`sort_index` applies to both series and data frames."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Multiple Columns\n",
"\n",
"We can also compute an aggregate over multiple columns at the same time. For example, if we want to look at the mean critic and audience scores of movies over time, we can group movies by year and take the mean of multiple columns.\n",
"\n",
"**If we have:** a data frame \n",
"**And we have:** one or more columns identifying group membership \n",
"**And we want:** a data frame with the same aggregate computed over all other columns in the frame \n",
"**Then we can:** apply `groupby` and the aggregate function without selecting columns.\n",
"\n",
"We're first going to select and rename columns, like we did at the end of the [Selection notebook](Selection.ipynb)."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" All Critics Top Critics Audience\n",
"year \n",
"1903 7.600000 0.000000 0.000000\n",
"1915 8.000000 0.000000 3.300000\n",
"1916 7.800000 0.000000 3.800000\n",
"1917 0.000000 0.000000 0.000000\n",
"1918 0.000000 0.000000 0.000000\n",
"... ... ... ...\n",
"2007 5.141278 4.769042 3.062162\n",
"2008 4.699357 4.383280 2.853698\n",
"2009 4.850000 4.700000 3.192308\n",
"2010 0.000000 0.000000 0.000000\n",
"2011 0.000000 0.000000 0.000000\n",
"\n",
"[98 rows x 3 columns]"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movie_scores.groupby('year').agg(np.mean)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No matter which method we used, we can then quickly do a line plot, which will default to plotting each column as a different colored line, with the index on the *x* axis:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"
"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"year_scores.plot.line()\n",
"plt.ylabel('Mean Average Score')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Other Grouping Modes\n",
"\n",
"There are a couple of other ways you can use `groupby` and aggregates:\n",
"\n",
"- Select multiple columns from the data frame grouper, by using a list of columns.\n",
"- Apply a different aggregate to each function by passing a dictionary to `agg`.\n",
"- Apply multiple aggregates to multiple columns by passing a list to `agg` *and* selecting a list of columns. The resulting data frame has a *hierarchical index* for its columns, which is honestly a little annoying to actually use.\n",
"- Group by multiple columns, resulting in a hierarchical index for the rows\n",
"\n",
"Experiment with these on your own!\n",
"\n",
"**Note:** if you use multiple columns, *and* one or more of the columns of the frame is a `Categorical`, groupby will produce a row for each *possible* value, even if one is never observed for that combination of the other grouping keys. To turn this off, pass the `observed=True` option to [`groupby`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Joining Frames\n",
"\n",
"We can *join* two frames together based on common values of one or more of their columns, possibly using indexes as well.\n",
"\n",
"The simplest way to join two frames without any indexes is with `pd.merge`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Column Join\n",
"\n",
"**If we have:** two data frames with at least one column in common \n",
"**And we want:** a data frame with rows based on matching the column values \n",
"**Then we can:** use `pd.merge` to join the frames.\n",
"\n",
"For example, to combine genres with titles:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
movieID
\n",
"
title
\n",
"
genre
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
Toy story
\n",
"
Adventure
\n",
"
\n",
"
\n",
"
1
\n",
"
1
\n",
"
Toy story
\n",
"
Animation
\n",
"
\n",
"
\n",
"
2
\n",
"
1
\n",
"
Toy story
\n",
"
Children
\n",
"
\n",
"
\n",
"
3
\n",
"
1
\n",
"
Toy story
\n",
"
Comedy
\n",
"
\n",
"
\n",
"
4
\n",
"
1
\n",
"
Toy story
\n",
"
Fantasy
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
20804
\n",
"
65126
\n",
"
Choke
\n",
"
Comedy
\n",
"
\n",
"
\n",
"
20805
\n",
"
65126
\n",
"
Choke
\n",
"
Drama
\n",
"
\n",
"
\n",
"
20806
\n",
"
65130
\n",
"
Revolutionary Road
\n",
"
Drama
\n",
"
\n",
"
\n",
"
20807
\n",
"
65130
\n",
"
Revolutionary Road
\n",
"
Romance
\n",
"
\n",
"
\n",
"
20808
\n",
"
65133
\n",
"
Blackadder Back & Forth
\n",
"
Comedy
\n",
"
\n",
" \n",
"
\n",
"
20809 rows × 3 columns
\n",
"
"
],
"text/plain": [
" movieID title genre\n",
"0 1 Toy story Adventure\n",
"1 1 Toy story Animation\n",
"2 1 Toy story Children\n",
"3 1 Toy story Comedy\n",
"4 1 Toy story Fantasy\n",
"... ... ... ...\n",
"20804 65126 Choke Comedy\n",
"20805 65126 Choke Drama\n",
"20806 65130 Revolutionary Road Drama\n",
"20807 65130 Revolutionary Road Romance\n",
"20808 65133 Blackadder Back & Forth Comedy\n",
"\n",
"[20809 rows x 3 columns]"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.merge(movies[['id', 'title']].rename(columns={'id': 'movieID'}),\n",
" movie_genres, on='movieID')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If there is more than one row in one table with a match for a value in the other table, it *duplicates* the other row. So we can see that “Toy story” is duplicated, once for each genre it appears in.\n",
"\n",
"Pull out the selection & rename on `movies` into a new cell for practice, and to see what it does."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Column/Index Join\n",
"\n",
"The `join` method can do index-index and column-index joins.\n",
"\n",
"**If we have:** a data frame \n",
"**And we have:** another data frame whose index is values appearing in a column of the first frame \n",
"**And we want:** a frame that merges the two frames by matching column values in the first with the index keys of the second \n",
"**Then we can:** use `.join` with the `on` option.\n",
"\n",
"To set this up, we want something with a suitable index. Let's create a frame that has mean & count of MovieLens user ratings:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" id title year MeanRating RatingCount\n",
"0 1 Toy story 1995 3.735154 1263.0\n",
"1 2 Jumanji 1995 2.976471 765.0\n",
"2 3 Grumpy Old Men 1993 2.873016 252.0\n",
"3 4 Waiting to Exhale 1995 2.577778 45.0\n",
"4 5 Father of the Bride Part II 1995 2.753333 225.0\n",
"... ... ... ... ... ...\n",
"10192 65088 Bedtime Stories 2008 3.500000 1.0\n",
"10193 65091 Manhattan Melodrama 1934 4.000000 1.0\n",
"10194 65126 Choke 2008 3.250000 2.0\n",
"10195 65130 Revolutionary Road 2008 2.500000 1.0\n",
"10196 65133 Blackadder Back & Forth 1999 4.000000 3.0\n",
"\n",
"[10197 rows x 5 columns]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movies[['id', 'title', 'year']].join(movie_stats, on='id')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we used the `id` column, which is in the `movies` table, as the `on` option. Join automatically matches it with the index in `movie_stats`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Index/Index Join\n",
"\n",
"Let's now see an index-index join.\n",
"\n",
"**If we have:** two data frames with matching indexes \n",
"**And we want:** a frame that merges the two frames matching their index values \n",
"**Then we can:** use `.join` with no extra options.\n",
"\n",
"Remember that `set_index` will set an index on the `movies` frame:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" title year MeanRating RatingCount\n",
"id \n",
"1 Toy story 1995 3.735154 1263.0\n",
"2 Jumanji 1995 2.976471 765.0\n",
"3 Grumpy Old Men 1993 2.873016 252.0\n",
"4 Waiting to Exhale 1995 2.577778 45.0\n",
"5 Father of the Bride Part II 1995 2.753333 225.0\n",
"... ... ... ... ...\n",
"65088 Bedtime Stories 2008 3.500000 1.0\n",
"65091 Manhattan Melodrama 1934 4.000000 1.0\n",
"65126 Choke 2008 3.250000 2.0\n",
"65130 Revolutionary Road 2008 2.500000 1.0\n",
"65133 Blackadder Back & Forth 1999 4.000000 3.0\n",
"\n",
"[10197 rows x 4 columns]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movies.set_index('id')[['title', 'year']].join(movie_stats)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This has the same result."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Join Types\n",
"\n",
"There are multiple types of joins. The types of Pandas joins correspond to SQL join types, if you are familiar with those.\n",
"\n",
"We refer to the frames as *left* and *right*. These correspond to positions in the functions as follows:\n",
"\n",
" pd.merge(left, right)\n",
" left.join(right)\n",
"\n",
"- An **inner join** requires a match to appear in both frames. If there is a row in one frame whose join column value has no match in the other frame, the row is excluded. This applies to both frames.\n",
"- A **left join** includes every row in the left-hand frame at least once; if there is a left-hand row with no match in the right-hand frame, one copy is included with missing values for all of the right-hand columns. Right-hand rows with no matches in the left frame are excluded.\n",
"- A **right join** is the reverse of a left join: it includes every value in the right-hand frame at least once.\n",
"- An **outer join** includes every row from both frames at least once.\n",
"\n",
"`pd.merge` defaults to an inner join, and `left.join(right)` defaults to a left join. Both take a `how=` option to change the merge type."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Join Tips\n",
"\n",
"The join I find myself using most frequently is a column-index join. I also usually join on a single column, although multiple-column joins are very well-supported."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tall and Wide\n",
"\n",
"As discussed in the video, data comes in *tall* and *wide* formats. If we observations of multiple variables for something, it can be in either format:\n",
"\n",
"- In **wide** format, each variable is a column\n",
"- In **tall** (or **long**) format, each variable produces a new row; there is a column for the variable name and another for the value\n",
"\n",
"We can convert back and forth between them."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tall to Wide\n",
"\n",
"The `pivot` function converts tall data to wide data.\n",
"\n",
"First, let's make some tall data. The movie-tags table has the tags that apply to each movie, along with their *weight*: how important that tag is. Let's look (joining to `tag` to get the tag names):"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
movieID
\n",
"
tagID
\n",
"
tagWeight
\n",
"
value
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
7
\n",
"
1
\n",
"
funny
\n",
"
\n",
"
\n",
"
1
\n",
"
1
\n",
"
13
\n",
"
3
\n",
"
time travel
\n",
"
\n",
"
\n",
"
2
\n",
"
1
\n",
"
25
\n",
"
3
\n",
"
tim allen
\n",
"
\n",
"
\n",
"
3
\n",
"
1
\n",
"
55
\n",
"
3
\n",
"
comedy
\n",
"
\n",
"
\n",
"
4
\n",
"
1
\n",
"
60
\n",
"
1
\n",
"
fun
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
51790
\n",
"
65037
\n",
"
792
\n",
"
1
\n",
"
autism
\n",
"
\n",
"
\n",
"
51791
\n",
"
65037
\n",
"
2214
\n",
"
1
\n",
"
internet
\n",
"
\n",
"
\n",
"
51792
\n",
"
65126
\n",
"
5281
\n",
"
1
\n",
"
based on book
\n",
"
\n",
"
\n",
"
51793
\n",
"
65126
\n",
"
13168
\n",
"
1
\n",
"
chuck palahniuk
\n",
"
\n",
"
\n",
"
51794
\n",
"
65130
\n",
"
2924
\n",
"
1
\n",
"
toplist08
\n",
"
\n",
" \n",
"
\n",
"
51795 rows × 4 columns
\n",
"
"
],
"text/plain": [
" movieID tagID tagWeight value\n",
"0 1 7 1 funny\n",
"1 1 13 3 time travel\n",
"2 1 25 3 tim allen\n",
"3 1 55 3 comedy\n",
"4 1 60 1 fun\n",
"... ... ... ... ...\n",
"51790 65037 792 1 autism\n",
"51791 65037 2214 1 internet\n",
"51792 65126 5281 1 based on book\n",
"51793 65126 13168 1 chuck palahniuk\n",
"51794 65130 2924 1 toplist08\n",
"\n",
"[51795 rows x 4 columns]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movie_tags.join(tags.set_index('id'), on='tagID')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`value` is a funny name, and once we have name we don't need tag ID, so let's clean up these columns:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
movieID
\n",
"
tag
\n",
"
weight
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
funny
\n",
"
1
\n",
"
\n",
"
\n",
"
1
\n",
"
1
\n",
"
time travel
\n",
"
3
\n",
"
\n",
"
\n",
"
2
\n",
"
1
\n",
"
tim allen
\n",
"
3
\n",
"
\n",
"
\n",
"
3
\n",
"
1
\n",
"
comedy
\n",
"
3
\n",
"
\n",
"
\n",
"
4
\n",
"
1
\n",
"
fun
\n",
"
1
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
51790
\n",
"
65037
\n",
"
autism
\n",
"
1
\n",
"
\n",
"
\n",
"
51791
\n",
"
65037
\n",
"
internet
\n",
"
1
\n",
"
\n",
"
\n",
"
51792
\n",
"
65126
\n",
"
based on book
\n",
"
1
\n",
"
\n",
"
\n",
"
51793
\n",
"
65126
\n",
"
chuck palahniuk
\n",
"
1
\n",
"
\n",
"
\n",
"
51794
\n",
"
65130
\n",
"
toplist08
\n",
"
1
\n",
"
\n",
" \n",
"
\n",
"
51795 rows × 3 columns
\n",
"
"
],
"text/plain": [
" movieID tag weight\n",
"0 1 funny 1\n",
"1 1 time travel 3\n",
"2 1 tim allen 3\n",
"3 1 comedy 3\n",
"4 1 fun 1\n",
"... ... ... ...\n",
"51790 65037 autism 1\n",
"51791 65037 internet 1\n",
"51792 65126 based on book 1\n",
"51793 65126 chuck palahniuk 1\n",
"51794 65130 toplist08 1\n",
"\n",
"[51795 rows x 3 columns]"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movie_tag_weights = movie_tags.join(tags.set_index('id'), on='tagID')\n",
"movie_tag_weights = movie_tag_weights[['movieID', 'value', 'tagWeight']]\n",
"movie_tag_weights = movie_tag_weights.rename(columns={\n",
" 'value': 'tag',\n",
" 'tagWeight': 'weight'\n",
"})\n",
"movie_tag_weights"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is in **tall** format: for each movie, we have a row for each tag with its weight.\n",
"\n",
"If we want to turn this into a (very!) **wide** table, with a column for each tag, we can use `pivot`.\n",
"\n",
"**If we have:** a data frame in tall format (one column has variable names, and another their values) \n",
"**And we want:** the same data in wide format (variables split out into columns) \n",
"**Then we can:** use `pivot` to pivot the wide data into tall format:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
tag
\n",
"
(s)vcd
\n",
"
007 (series)
\n",
"
15th century
\n",
"
16mm
\n",
"
16th century
\n",
"
17th century
\n",
"
1800s
\n",
"
1890s
\n",
"
18th century
\n",
"
1900s
\n",
"
...
\n",
"
zeppelin
\n",
"
zero mostel
\n",
"
zibri studio
\n",
"
zim
\n",
"
ziyi zhang
\n",
"
zombie
\n",
"
zombie movie
\n",
"
zombies
\n",
"
zoo
\n",
"
zooey deschanel
\n",
"
\n",
"
\n",
"
movieID
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
1
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
2
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
3
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
5
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
6
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
64993
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
65006
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
65037
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
65126
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
65130
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
" \n",
"
\n",
"
7155 rows × 5297 columns
\n",
"
"
],
"text/plain": [
"tag (s)vcd 007 (series) 15th century 16mm 16th century 17th century \\\n",
"movieID \n",
"1 NaN NaN NaN NaN NaN NaN \n",
"2 NaN NaN NaN NaN NaN NaN \n",
"3 NaN NaN NaN NaN NaN NaN \n",
"5 NaN NaN NaN NaN NaN NaN \n",
"6 NaN NaN NaN NaN NaN NaN \n",
"... ... ... ... ... ... ... \n",
"64993 NaN NaN NaN NaN NaN NaN \n",
"65006 NaN NaN NaN NaN NaN NaN \n",
"65037 NaN NaN NaN NaN NaN NaN \n",
"65126 NaN NaN NaN NaN NaN NaN \n",
"65130 NaN NaN NaN NaN NaN NaN \n",
"\n",
"tag 1800s 1890s 18th century 1900s ... zeppelin zero mostel \\\n",
"movieID ... \n",
"1 NaN NaN NaN NaN ... NaN NaN \n",
"2 NaN NaN NaN NaN ... NaN NaN \n",
"3 NaN NaN NaN NaN ... NaN NaN \n",
"5 NaN NaN NaN NaN ... NaN NaN \n",
"6 NaN NaN NaN NaN ... NaN NaN \n",
"... ... ... ... ... ... ... ... \n",
"64993 NaN NaN NaN NaN ... NaN NaN \n",
"65006 NaN NaN NaN NaN ... NaN NaN \n",
"65037 NaN NaN NaN NaN ... NaN NaN \n",
"65126 NaN NaN NaN NaN ... NaN NaN \n",
"65130 NaN NaN NaN NaN ... NaN NaN \n",
"\n",
"tag zibri studio zim ziyi zhang zombie zombie movie zombies zoo \\\n",
"movieID \n",
"1 NaN NaN NaN NaN NaN NaN NaN \n",
"2 NaN NaN NaN NaN NaN NaN NaN \n",
"3 NaN NaN NaN NaN NaN NaN NaN \n",
"5 NaN NaN NaN NaN NaN NaN NaN \n",
"6 NaN NaN NaN NaN NaN NaN NaN \n",
"... ... ... ... ... ... ... ... \n",
"64993 NaN NaN NaN NaN NaN NaN NaN \n",
"65006 NaN NaN NaN NaN NaN NaN NaN \n",
"65037 NaN NaN NaN NaN NaN NaN NaN \n",
"65126 NaN NaN NaN NaN NaN NaN NaN \n",
"65130 NaN NaN NaN NaN NaN NaN NaN \n",
"\n",
"tag zooey deschanel \n",
"movieID \n",
"1 NaN \n",
"2 NaN \n",
"3 NaN \n",
"5 NaN \n",
"6 NaN \n",
"... ... \n",
"64993 NaN \n",
"65006 NaN \n",
"65037 NaN \n",
"65126 NaN \n",
"65130 NaN \n",
"\n",
"[7155 rows x 5297 columns]"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mtw_wide = movie_tag_weights.pivot('movieID', 'tag', 'weight')\n",
"mtw_wide"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see a lot of missing values (NaN). The `describe` method on a data frame will describe all the columns, which will include counting the values. Let's see it:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
],
"text/plain": [
" count mean std min 25% 50% 75% max\n",
"tag \n",
"(s)vcd 31.0 1.032258 0.179605 1.0 1.0 1.0 1.0 2.0\n",
"007 (series) 23.0 1.043478 0.208514 1.0 1.0 1.0 1.0 2.0\n",
"15th century 2.0 1.000000 0.000000 1.0 1.0 1.0 1.0 1.0\n",
"16mm 5.0 1.000000 0.000000 1.0 1.0 1.0 1.0 1.0\n",
"16th century 6.0 1.000000 0.000000 1.0 1.0 1.0 1.0 1.0\n",
"... ... ... ... ... ... ... ... ...\n",
"zombie 25.0 1.520000 0.871780 1.0 1.0 1.0 2.0 4.0\n",
"zombie movie 3.0 2.000000 1.000000 1.0 1.5 2.0 2.5 3.0\n",
"zombies 43.0 3.465116 3.607854 1.0 1.0 2.0 5.0 19.0\n",
"zoo 2.0 1.000000 0.000000 1.0 1.0 1.0 1.0 1.0\n",
"zooey deschanel 2.0 1.000000 0.000000 1.0 1.0 1.0 1.0 1.0\n",
"\n",
"[5297 rows x 8 columns]"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mtw_desc.T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ok isn't that kinda cool?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Stacking Frames\n",
"\n",
"Joins let us combine by merging on values, but sometimes we want to stack data frames on top of each other. The [`concat`](https://pandas.pydata.org/docs/reference/api/pandas.concat.html) Pandas function concatenates a list (or other iterable) of data frames. For example, to simulate a `melt` of the two critic rating columns:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"movie_top_rates = movies[['id', 'rtTopCriticsRating']].rename(columns={'rtTopCriticsRating': 'rating'})\n",
"movie_top_rates['source'] = 'Top Critics'\n",
"movie_all_rates = movies[['id', 'rtAllCriticsRating']].rename(columns={'rtAllCriticsRating': 'rating'})\n",
"movie_all_rates['source'] = 'All Critics'"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
id
\n",
"
rating
\n",
"
source
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
8.5
\n",
"
Top Critics
\n",
"
\n",
"
\n",
"
1
\n",
"
2
\n",
"
5.8
\n",
"
Top Critics
\n",
"
\n",
"
\n",
"
2
\n",
"
3
\n",
"
7.0
\n",
"
Top Critics
\n",
"
\n",
"
\n",
"
3
\n",
"
4
\n",
"
5.5
\n",
"
Top Critics
\n",
"
\n",
"
\n",
"
4
\n",
"
5
\n",
"
5.4
\n",
"
Top Critics
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
20389
\n",
"
65088
\n",
"
4.4
\n",
"
All Critics
\n",
"
\n",
"
\n",
"
20390
\n",
"
65091
\n",
"
7.0
\n",
"
All Critics
\n",
"
\n",
"
\n",
"
20391
\n",
"
65126
\n",
"
5.6
\n",
"
All Critics
\n",
"
\n",
"
\n",
"
20392
\n",
"
65130
\n",
"
6.7
\n",
"
All Critics
\n",
"
\n",
"
\n",
"
20393
\n",
"
65133
\n",
"
0.0
\n",
"
All Critics
\n",
"
\n",
" \n",
"
\n",
"
20394 rows × 3 columns
\n",
"
"
],
"text/plain": [
" id rating source\n",
"0 1 8.5 Top Critics\n",
"1 2 5.8 Top Critics\n",
"2 3 7.0 Top Critics\n",
"3 4 5.5 Top Critics\n",
"4 5 5.4 Top Critics\n",
"... ... ... ...\n",
"20389 65088 4.4 All Critics\n",
"20390 65091 7.0 All Critics\n",
"20391 65126 5.6 All Critics\n",
"20392 65130 6.7 All Critics\n",
"20393 65133 0.0 All Critics\n",
"\n",
"[20394 rows x 3 columns]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"movie_rates = pd.concat([movie_top_rates, movie_all_rates], ignore_index=True)\n",
"movie_rates"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `ignore_index=True` option causes `pd.concat` to throw away the indexes and make a new `RangeIndex`. This is fine because the indexes don't contain any useful information.\n",
"\n",
"We can also concatenate with the index; this is most useful when the frames have disjoint indexes, or when we want to add another index level containing the source. We'll discuss this in the indexing notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Wide to Tall\n",
"\n",
"What if we want to go the other way? That's what `melt` is for.\n",
"\n",
"Remember our movie stats by year?"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
All Critics
\n",
"
Top Critics
\n",
"
Audience
\n",
"
\n",
"
\n",
"
year
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
1903
\n",
"
7.600000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
1915
\n",
"
8.000000
\n",
"
0.000000
\n",
"
3.300000
\n",
"
\n",
"
\n",
"
1916
\n",
"
7.800000
\n",
"
0.000000
\n",
"
3.800000
\n",
"
\n",
"
\n",
"
1917
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
1918
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
2007
\n",
"
5.141278
\n",
"
4.769042
\n",
"
3.062162
\n",
"
\n",
"
\n",
"
2008
\n",
"
4.699357
\n",
"
4.383280
\n",
"
2.853698
\n",
"
\n",
"
\n",
"
2009
\n",
"
4.850000
\n",
"
4.700000
\n",
"
3.192308
\n",
"
\n",
"
\n",
"
2010
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
2011
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
" \n",
"
\n",
"
98 rows × 3 columns
\n",
"
"
],
"text/plain": [
" All Critics Top Critics Audience\n",
"year \n",
"1903 7.600000 0.000000 0.000000\n",
"1915 8.000000 0.000000 3.300000\n",
"1916 7.800000 0.000000 3.800000\n",
"1917 0.000000 0.000000 0.000000\n",
"1918 0.000000 0.000000 0.000000\n",
"... ... ... ...\n",
"2007 5.141278 4.769042 3.062162\n",
"2008 4.699357 4.383280 2.853698\n",
"2009 4.850000 4.700000 3.192308\n",
"2010 0.000000 0.000000 0.000000\n",
"2011 0.000000 0.000000 0.000000\n",
"\n",
"[98 rows x 3 columns]"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"year_scores"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**If we have:** a data frame in wide format \n",
"**And we want:** the same data in tall format \n",
"**Then we can:** use the `melt` method or function.\n",
"\n",
"We first have to reset the index, because melt destroys it:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
year
\n",
"
All Critics
\n",
"
Top Critics
\n",
"
Audience
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1903
\n",
"
7.600000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
1
\n",
"
1915
\n",
"
8.000000
\n",
"
0.000000
\n",
"
3.300000
\n",
"
\n",
"
\n",
"
2
\n",
"
1916
\n",
"
7.800000
\n",
"
0.000000
\n",
"
3.800000
\n",
"
\n",
"
\n",
"
3
\n",
"
1917
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
4
\n",
"
1918
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
93
\n",
"
2007
\n",
"
5.141278
\n",
"
4.769042
\n",
"
3.062162
\n",
"
\n",
"
\n",
"
94
\n",
"
2008
\n",
"
4.699357
\n",
"
4.383280
\n",
"
2.853698
\n",
"
\n",
"
\n",
"
95
\n",
"
2009
\n",
"
4.850000
\n",
"
4.700000
\n",
"
3.192308
\n",
"
\n",
"
\n",
"
96
\n",
"
2010
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
97
\n",
"
2011
\n",
"
0.000000
\n",
"
0.000000
\n",
"
0.000000
\n",
"
\n",
" \n",
"
\n",
"
98 rows × 4 columns
\n",
"
"
],
"text/plain": [
" year All Critics Top Critics Audience\n",
"0 1903 7.600000 0.000000 0.000000\n",
"1 1915 8.000000 0.000000 3.300000\n",
"2 1916 7.800000 0.000000 3.800000\n",
"3 1917 0.000000 0.000000 0.000000\n",
"4 1918 0.000000 0.000000 0.000000\n",
".. ... ... ... ...\n",
"93 2007 5.141278 4.769042 3.062162\n",
"94 2008 4.699357 4.383280 2.853698\n",
"95 2009 4.850000 4.700000 3.192308\n",
"96 2010 0.000000 0.000000 0.000000\n",
"97 2011 0.000000 0.000000 0.000000\n",
"\n",
"[98 rows x 4 columns]"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"year_scores.reset_index()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That pops the year back out to being a column, so we can pass it as the `id_var` to `melt`:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"