TidyData: Horizontal Conditions#
When extracting data there will be columns whose value will depend conditionally on the values of other columns. In tidychef we handle this scenario with what we call HorizontalConditions.
Source Data#
The data source we’re using for these examples is shown below:
The full data source can be viewed here.
from tidychef import acquire, preview
from tidychef.selection import CsvSelectable
table: CsvSelectable = acquire.csv.http("https://raw.githubusercontent.com/mikeAdamss/tidychef/main/tests/fixtures/csv/bands-wide.csv")
preview(table)
Unnamed Table
| A | B | C | D | E | F | G | H | I | J | K | |
| 1 | |||||||||||
| 2 | Houses | Cars | Boats | Houses | Cars | Boats | |||||
| 3 | Beatles | Rolling Stones | |||||||||
| 4 | John | 1 | 5 | 9 | Keith | 2 | 6 | 10 | |||
| 5 | Paul | 2 | 6 | 10 | Mick | 3 | 7 | 11 | |||
| 6 | George | 2 | 7 | 11 | Charlie | 3 | 8 | 12 | |||
| 7 | Ringo | 4 | 8 | 12 | Ronnie | 5 | 9 | 13 | |||
| 8 |
Syntax#
The basic syntax for constructing a horizontal conditional is as follows:
Column.horizontal_condition(<name>, <callable>)
The <callable> is a python function or lambda function that operates upon a dictionary.
The Horizontal Condition Dictionary#
The dictionary in question consists of:
keys: the names of the extracted columns
values: the values extracted against the same observation the horoxontal condition is operating against.
Example:
Let’s imagine the you run a transform that will create the following line of tidy data.
Observation |
Member |
Assets |
Band |
|---|---|---|---|
5 |
John |
Cars |
Beatles |
If you were to add a horizonal condition to the TidyData constructor, then for that specific observation the dictionary accessible to the horizontal condition would be:
{
"Observation": "5",
"Member": "John",
"Assets": "Cars",
"Band" : "Beatles
}
This will be shown in context in the examples below.
Condition: Singer In The Beatles#
For our first example, we’ll create a horizontal condition columns to identify members of The Rolling Stones whose names end with “e”.
You’ve seen this example before, so mainly focus on the new Column.horizontal_condition() syntax.
from typing import Dict
from tidychef import acquire, preview, filters
from tidychef.direction import right, below
from tidychef.selection import CsvSelectable, filters
from tidychef.output import TidyData, Column
table: CsvSelectable = acquire.csv.http("https://raw.githubusercontent.com/mikeAdamss/tidychef/main/tests/fixtures/csv/bands-wide.csv")
def e_ending_stones(line: Dict[str, str]) -> str:
"""
Returns "True" as string if member ends with "e"
and band is "Rolling Stones"
"""
if line["Member"].endswith("e") and line["Band"] == "Rolling Stones":
return "True"
return "False"
observations = table.filter(filters.is_numeric).label_as("Observation")
bands = (table.excel_ref("A3") | table.excel_ref("G3")).label_as("Band")
assets = table.excel_ref('2').is_not_blank().label_as("Asset")
members = (table.excel_ref("B") | table.excel_ref("H")).is_not_blank().label_as("Member")
preview(observations, bands, assets, members)
tidy_data = TidyData(
observations,
Column(bands.attach_closest(right)),
Column(assets.attach_directly(below)),
Column(members.attach_directly(right)),
Column.horizontal_condition("Stones ending with e", e_ending_stones)
)
print(tidy_data)
| Observation |
| Band |
| Asset |
| Member |
Unnamed Table
| A | B | C | D | E | F | G | H | I | J | K | |
| 1 | |||||||||||
| 2 | Houses | Cars | Boats | Houses | Cars | Boats | |||||
| 3 | Beatles | Rolling Stones | |||||||||
| 4 | John | 1 | 5 | 9 | Keith | 2 | 6 | 10 | |||
| 5 | Paul | 2 | 6 | 10 | Mick | 3 | 7 | 11 | |||
| 6 | George | 2 | 7 | 11 | Charlie | 3 | 8 | 12 | |||
| 7 | Ringo | 4 | 8 | 12 | Ronnie | 5 | 9 | 13 | |||
| 8 |
| Observation | Band | Asset | Member | Stones ending with e |
| 1 | Beatles | Houses | John | False |
| 5 | Beatles | Cars | John | False |
| 9 | Beatles | Boats | John | False |
| 2 | Rolling Stones | Houses | Keith | False |
| 6 | Rolling Stones | Cars | Keith | False |
| 10 | Rolling Stones | Boats | Keith | False |
| 2 | Beatles | Houses | Paul | False |
| 6 | Beatles | Cars | Paul | False |
| 10 | Beatles | Boats | Paul | False |
| 3 | Rolling Stones | Houses | Mick | False |
| 7 | Rolling Stones | Cars | Mick | False |
| 11 | Rolling Stones | Boats | Mick | False |
| 2 | Beatles | Houses | George | False |
| 7 | Beatles | Cars | George | False |
| 11 | Beatles | Boats | George | False |
| 3 | Rolling Stones | Houses | Charlie | True |
| 8 | Rolling Stones | Cars | Charlie | True |
| 12 | Rolling Stones | Boats | Charlie | True |
| 4 | Beatles | Houses | Ringo | False |
| 8 | Beatles | Cars | Ringo | False |
| 12 | Beatles | Boats | Ringo | False |
| 5 | Rolling Stones | Houses | Ronnie | True |
| 9 | Rolling Stones | Cars | Ronnie | True |
| 13 | Rolling Stones | Boats | Ronnie | True |