IN2039: Data Visualization for Decision Making
Department of Industrial Engineering
Remember to load the Python libraries into Google Colab before we start:
“Tidy datasets are easy to manipulate, model, and visualize.” — Hadley Wickham
In tidy data:

Consider four datasets with the same values of four variables country, year, population, and cases. First, this is tidy version.
| country | year | cases | population | |
|---|---|---|---|---|
| 0 | Afghanistan | 1999 | 745 | 19987071 |
| 1 | Afghanistan | 2000 | 2666 | 20595360 |
| 2 | Brazil | 1999 | 37737 | 172006362 |
| 3 | Brazil | 2000 | 80488 | 174504898 |
| 4 | China | 1999 | 212258 | 1272915272 |
| 5 | China | 2000 | 213766 | 1280428583 |
This is tidy data because each variable is in a column , each observation is in a row, and each cell is a single measurement.
| country | year | cases | population | |
|---|---|---|---|---|
| 0 | Afghanistan | 1999 | 745 | 19987071 |
| 1 | Afghanistan | 2000 | 2666 | 20595360 |
| 2 | Brazil | 1999 | 37737 | 172006362 |
| 3 | Brazil | 2000 | 80488 | 174504898 |
| 4 | China | 1999 | 212258 | 1272915272 |
| 5 | China | 2000 | 213766 | 1280428583 |
Consider another version:
| country | year | type | count | |
|---|---|---|---|---|
| 0 | Afghanistan | 1999 | cases | 745 |
| 1 | Afghanistan | 1999 | population | 19987071 |
| 2 | Afghanistan | 2000 | cases | 2666 |
| 3 | Afghanistan | 2000 | population | 20595360 |
| 4 | Brazil | 1999 | cases | 37737 |
| 5 | Brazil | 1999 | population | 172006362 |
Not tidy because the last column is a summary statistic (count) of two variables.
Consider another version:
| country | year | rate | |
|---|---|---|---|
| 0 | Afghanistan | 1999 | 745/19987071 |
| 1 | Afghanistan | 2000 | 2666/20595360 |
| 2 | Brazil | 1999 | 37737/172006362 |
| 3 | Brazil | 2000 | 80488/174504898 |
| 4 | China | 1999 | 212258/1272915272 |
| 5 | China | 2000 | 213766/1280428583 |
Not tidy because the last column is a summary statistic (rate) of two variables, or there are two measurements involved in this column.
Consider one last version involving two datasets.
| country | 1999 | 2000 | |
|---|---|---|---|
| 0 | Afghanistan | 745 | 2666 |
| 1 | Brazil | 37737 | 80488 |
| 2 | China | 212258 | 213766 |
| country | 1999 | 2000 | |
|---|---|---|---|
| 0 | Afghanistan | 19987071 | 20595360 |
| 1 | Brazil | 172006362 | 174504898 |
| 2 | China | 1272915272 | 1280428583 |
Not tidy data!
The pandas library provides several functions for reshaping, organizing, and completing datasets.
Here, we will discuss some of the most common ones:
| Purpose | Function 1 | Function 2 |
|---|---|---|
| Pivoting | melt() |
pivot() |
| Splitting / Combining | str.split() |
str.cat() |
| Missing values | fillna() |
dropna() |
| Combining tables | merge() |
concat() |
Consider the data in the file “spotify.xlsx”. This dataset contains the global daily plays of the five most popular songs on the Spotify music streaming service in 2017.
Let’s read the dataset using the .read_excel() function from the pandas library.
Let’s preview the dataset.
.melt()A common problem is a dataset where some of the column names are not names of variables, but values of a variable.
The .melt() function transforms columns into rows (converts data from wide to long format). Let’s apply it to spotify_data.
Python allows column names to contain spaces and special characters because they are stored as strings.
For example, columns such as "Shape of You" or "Something Just Like This" can be referenced directly inside quotation marks.
When using pandas, column names are almost always written as strings enclosed in quotation marks.
Song column with the names of the songs.Plays column with the number of plays for each song and date..pivot()The .pivot() function is the opposite of melt(). We use it when an observation is scattered across multiple rows and we want to convert the dataset back to a wide format.
Consider an industrial engineer who receives a messy Excel file from a manufacturing client. The data file is called “industrial_dataset.xlsx”, which file includes data about machine maintenance logs, production output, and operator comments.
We use this dataset to illustrate the functions .str.split() and .str.cat().
.str.split()The .str.split() function separates the contents of one column into multiple columns by splitting the text wherever a separator appears. Consider the Comment column.
The column has some values such as “Requires part: valve” and “Delay: maintenance” that we may want to split into columns.
0 ok
1 ok
2 Needs oil!
3 All good\n
4 All good\n
...
95 Requires part: valve
96 ok
97 Delay: maintenance\n
98 Needs oil!
99 All good\n
Name: Comment, Length: 100, dtype: object
We can split the values in the column according to “:”.
That is, everything before the colon will be in a column. Everything after the colon will be in another column. To achieve this, we use the function .str.split().
One input of the function is the symbol or character for which we cant to make a split. The other input, expand = True tells Python that we want to create new columns.
The result is two columns.
We can assign them to new columns in the dataset using the following code.
| Machine ID | Output (units) | Maintenance Date | Operator | Comment | First_comment | Second_comment | |
|---|---|---|---|---|---|---|---|
| 0 | 101 | 1200 | 2023-01-10 | Ana | ok | ok | None |
| 1 | 101 | 1200 | 2023-01-10 | Ana | ok | ok | None |
| 2 | 102 | 1050 | 2023-01-12 | Bob | Needs oil! | Needs oil! | None |
| 3 | 103 | error | 2023-01-13 | Charlie | All good\n | All good\n | None |
.str.cat()The .str.cat() function performs the opposite operation. It combines multiple text columns into a single column.
The first object is the column that starts the concatenation, and the remaining columns are added using str.cat().
.drop()Next, we add the new column to the original dataset and remove the other columns First_comment and Second_comment using the function .drop() from pandas.
The result is in the combined_data dataframe.
Data wrangling is the process of transforming raw data into a clean and structured format.
It involves merging, reshaping, filtering, and organizing data for analysis.
Here, we illustrate some special functions of the pandas for cleaning common issues with a dataset.
Duplicate or identical rows are rows that have the same entries in every column in the dataset.
If only one row is needed for the analysis, we can remove the duplicates using the .drop_duplicates() function.
The industrial_data_single does not have duplicate rows.
Sometimes there are columns with missing values. In Python, missing values are denoted by NaN (Not a Number).
If we would like to fill them with a value or text, we use the .fillna() function. In this function, we use the syntaxis 'Variable': 'Replace', where the Variable is the column in the dataset and Replace is the text or number to fill the entry in.
Let’s fill in the missing entries of the columns Operator, Maintenance Date, and Comment.
There are some cases in which columns have some undesired or unwatned values. Consider the Output (units) as an example.
0 1200
1 1200
2 1050
3 error
4 950
Name: Output (units), dtype: object
The column has the numbers of units but also text such as “error”.
We can replace the “error” in this column by a user-specified value, say, NaN. To this end, we use the function .replace(). The function has two inputs. The first one is the value to replace and the second one is the replacement value.
The
float('nan')allows the column to be numeric.
Let’s check the new column’s information.
<class 'pandas.core.series.Series'>
RangeIndex: 100 entries, 0 to 99
Series name: Output (units)
Non-Null Count Dtype
-------------- -----
84 non-null float64
dtypes: float64(1)
memory usage: 928.0 bytes
Note that the new column is now numeric.
Something that we notice is that the column First_Comment has some extra characters like “” that may be useless when working with the data.
We can remove them using the function .str.strip(). The input of the function is the character to remove.
Let’s see the cleaned column.
We can also remove other characters.
When working with text columns such as those containing names, it might be possible to have different ways of writing. A common case is when having lower case or upper case names or a combination thereof.
For example, consider the column Operator containing the names of the operators.
To deal with names, we first use the .str.strip() to remove leading and trailing characters from strings.
We can turn all names to lowercase using the function str.lower().
We can turn all names to lowercase using the function str.upper().
We can convert all names to title case using the function str.title().

Tecnologico de Monterrey