Python Altair Combines Filtering, Grouping, and Merging into a Single Data Visualization | by Soner Yıldırım | Towards Data Science

Altair is a statistical data visualization library for Python. It provides a simple and easy-to-understand syntax for creating both static and interactive visualizations.
What I think separates Altair from other common data visualization libraries is that it integrates data analysis components into the visualizations seamlessly. Thus, it serves as a highly practical tool for data exploration.
In this article, we will see, step-by-step, how to create a visualization that includes filtering, grouping, and merging operations. Eventually, we will create an informative plot that can be used as part of an exploratory data analysis process.
We first generate mock data which consists of two data frames. The first one contains restaurant orders and the other one contains the prices of the items placed in the orders.
# import librariesimport numpy as npimport pandas as pdimport altair as altimport random# mock dataorders = pd.DataFrame({   "order_id": np.arange(1,101),   "item": np.random.randint(1, 50, size=100),   "qty": np.random.randint(1, 10, size=100),   "tip": (np.random.random(100) * 10).round(2)})prices = pd.DataFrame({   "item": np.arange(1,51),   "price": (np.random.random(50) * 50).round(2)})order_type = ["lunch", "dinner"] * 50random.shuffle(order_type)orders["order_type"] = order_type
The values are generated using numpy functions. Then, we add order type using a list of 100 items. The shuffle function under the random module of Python is used for randomizing the list.
Let’s take a look at the data frames we have just created.
You may argue that we can have the item prices in the orders table. We designed the data frames this way to be able to use the merging operation. Besides, it slightly demonstrates the idea of relational databases.
Let’s first create a simple plot to introduce the structure of Altair syntax.
alt.Chart(orders).mark_circle(size=50).encode(   x="qty", y="tip", color="order_type").properties(   title = "Tip vs Quantity")
We start by passing the data to a top-level Chart object. The data can be in the form of a Pandas data frame or a URL string pointing to a json or csv file. Then, the type of visualization (e.g. mark_circle, mark_line, and so on) is selected.
The encode function specifies what to plot in the given data frame. Thus, anything we write in the encode function must be linked to the data frame. Finally, we specify certain properties of the plot using the properties function.
Consider a case where we need to create a scatter plot of the price and tip values. They are in different data frames. One option is to merge two data frames and use these two columns in a scatter plot.
Altair offers a more practical way. It allows for looking up a column in a different data frame. The intuition is the same as the merge function of Pandas.
alt.Chart(orders).mark_circle(size=50).encode(   x="tip", y="price:Q", color="order_type").transform_lookup(   lookup="item",   from_=alt.LookupData(data=prices, key="item", fields=["price"])).properties(   title = "Price vs Tip")
The transform_lookup function is similar to the merge function of Pandas. The column used for matching the observations (i.e. rows) is passed to the lookup parameter. The fields parameter is used for selecting the desired columns from the other data frame.
We can also integrate a filtering component to our plot. Let’s plot the data points with a price of more than 10 dollars.
alt.Chart(orders).mark_circle(size=50).encode(   x="tip", y="price:Q", color="order_type").transform_lookup(   lookup="item",   from_=alt.LookupData(data=prices, key="item", fields=["price"])).transform_filter(   alt.FieldGTPredicate(field='price', gt=10)).properties(   title = "Price vs Tip")
The transform_filter function is used for filtering. The FieldGTPredicate handles “greater than” conditions. Altair also provides predicates for other conditions such as “equal”, “less than”, “range”, and so on.
In addition to filtering and merging, Altair allows for grouping the data points before plotting. For instance, we can create a bar plot that shows the average price of items for each order type. Furthermore, we can perform this operation for items that cost less than 20 dollars.
alt.Chart(orders).mark_bar().encode(   y="order_type", x="avg_price:Q").transform_lookup(   lookup="item",   from_=alt.LookupData(data=prices, key="item", fields=["price"])).transform_filter(   alt.FieldLTPredicate(field='price', lt=20)).transform_aggregate(   avg_price = "mean(price)", groupby = ["order_type"]).properties(   height=200, width=300)
Let’s elaborate on each step:
transform_lookup: Looks up the price from the prices data frame.
transform_filter: Filter the prices that are less than 20 dollars.
transform_aggregate: Groups the prices by order type and calculates the mean.
Make sure you pass the name of the aggregated column to the encode function.
Filtering, merging, and grouping are essential to an exploratory data analysis process. Altair allows for performing all of these operations while creating data visualizations. In that sense, Altair can also be considered as a data analysis tool.
The examples we have done in the article may not seem so useful but they clearly explain how these components are used in the visualizations.
Thank you for reading. Please let me know if you have any feedback.