Selection: Shift#
The shift()
method is move selections of cells in cardinal directions.
This page will show examples of how to do this, along with some simple examples of how you’d use this functionality.’
Source Data#
The data source we’re using for these examples is shown below:
Note - this particular table has some very verbose headers we don’t care about, so we’ll be using |
---|
The full data source can be downloaded here. We’ll be using th 10th tab named “Table 3c”.
from tidychef import acquire, preview
from tidychef.selection import XlsxSelectable
table: XlsxSelectable = acquire.xlsx.http("https://github.com/mikeAdamss/tidychef/raw/main/tests/fixtures/xlsx/ons-oic.xlsx", tables="Table 3c")
preview(table, bounded="A4:H10")
Table 3c
A | B | C | D | E | F | G | H | |
4 | Percentage change 3 months on previous 3 months | |||||||
5 | Time period | Public new housing | Private new housing | Total new housing | Infrastructure new work | Public other new work | Private industrial new work | Private commercial new work |
6 | Dataset identifier code | MVO6 | MVO7 | MVO8 | MVO9 | MVP2 | MVP3 | MVP4 |
7 | Jun 2010 | 5.6 | 9.8 | 8.8 | 3 | 4.3 | 3.7 | 1.9 |
8 | Jul 2010 | 2 | 5.6 | 4.8 | 0.2 | -0.2 | 9.7 | 3.5 |
9 | Aug 2010 | 5.5 | 4.5 | 4.7 | -2.9 | -2.9 | 24.4 | 5.9 |
10 | Sep 2010 | 11.7 | 7.5 | 8.5 | -6.8 | -3.3 | 16.1 | 5.3 |
Shifting Single Directions#
In the following example, we’re going to create one selection by just shifting another selection down.
from tidychef import acquire, preview
from tidychef.selection import XlsxSelectable
from tidychef.direction import right, down
table: XlsxSelectable = acquire.xlsx.http("https://github.com/mikeAdamss/tidychef/raw/main/tests/fixtures/xlsx/ons-oic.xlsx", tables="Table 3c")
# Make the original selection
original_selection = table.excel_ref("B6").expand(right).label_as("Original Selection")
# Create a second selection by shifting the first selection down once
shifted_selection = original_selection.shift(down).label_as("Shifted Selection")
preview(shifted_selection, original_selection, bounded="A4:H10")
Shifted Selection |
Original Selection |
Table 3c
A | B | C | D | E | F | G | H | |
4 | Percentage change 3 months on previous 3 months | |||||||
5 | Time period | Public new housing | Private new housing | Total new housing | Infrastructure new work | Public other new work | Private industrial new work | Private commercial new work |
6 | Dataset identifier code | MVO6 | MVO7 | MVO8 | MVO9 | MVP2 | MVP3 | MVP4 |
7 | Jun 2010 | 5.6 | 9.8 | 8.8 | 3 | 4.3 | 3.7 | 1.9 |
8 | Jul 2010 | 2 | 5.6 | 4.8 | 0.2 | -0.2 | 9.7 | 3.5 |
9 | Aug 2010 | 5.5 | 4.5 | 4.7 | -2.9 | -2.9 | 24.4 | 5.9 |
10 | Sep 2010 | 11.7 | 7.5 | 8.5 | -6.8 | -3.3 | 16.1 | 5.3 |
Shifting Across More Than One Cell#
In this case we’re going to shift across multiple cells by passing integers to the direction.
In particular, take note of the use of right(3)
.
from tidychef import acquire, preview
from tidychef.selection import XlsxSelectable
from tidychef.direction import right, down
table: XlsxSelectable = acquire.xlsx.http("https://github.com/mikeAdamss/tidychef/raw/main/tests/fixtures/xlsx/ons-oic.xlsx", tables="Table 3c")
# Make the original selection
original_selection = table.excel_ref("B7").expand(down).label_as("Original Selection")
# Create a second selection by shifting the first selection right three columns
shifted_selection = original_selection.shift(right(3)).label_as("Shifted Selection")
preview(shifted_selection, original_selection, bounded="A4:H10")
Shifted Selection |
Original Selection |
Table 3c
A | B | C | D | E | F | G | H | |
4 | Percentage change 3 months on previous 3 months | |||||||
5 | Time period | Public new housing | Private new housing | Total new housing | Infrastructure new work | Public other new work | Private industrial new work | Private commercial new work |
6 | Dataset identifier code | MVO6 | MVO7 | MVO8 | MVO9 | MVP2 | MVP3 | MVP4 |
7 | Jun 2010 | 5.6 | 9.8 | 8.8 | 3 | 4.3 | 3.7 | 1.9 |
8 | Jul 2010 | 2 | 5.6 | 4.8 | 0.2 | -0.2 | 9.7 | 3.5 |
9 | Aug 2010 | 5.5 | 4.5 | 4.7 | -2.9 | -2.9 | 24.4 | 5.9 |
10 | Sep 2010 | 11.7 | 7.5 | 8.5 | -6.8 | -3.3 | 16.1 | 5.3 |
An example of using shifts#
In keeping with tidychefs dot notation approach you can chain multiple shift commands to enable movement in a diagonal or otherwise more nuanced direction.
Note - we’re using an |
---|
from tidychef import acquire, preview
from tidychef.selection import XlsxSelectable
from tidychef.direction import right, down, up
table: XlsxSelectable = acquire.xlsx.http("https://github.com/mikeAdamss/tidychef/raw/main/tests/fixtures/xlsx/ons-oic.xlsx", tables="Table 3c")
anchor = table.excel_ref("A6").label_as("This is our anchor, you'd not always preview and never extract this")
# shift right then down, the expand right then down to get observations
observations = anchor.shift(right).shift(down).expand(right).expand(down).label_as("Value")
# shift both up and right to get housing
housing = anchor.shift(right).shift(up).expand(right).label_as("Housing")
# shift right then expand to get the dataset identifier codes
dataset_identifier_codes = anchor.shift(right).expand(right).label_as("Dataset Identifier Code")
# shift down then expand down to get the year
period = anchor.shift(down).expand(down).label_as("Period")
preview(anchor, observations, housing, dataset_identifier_codes, period, bounded="A4:H10")
This is our anchor, you'd not always preview and never extract this |
Value |
Housing |
Dataset Identifier Code |
Period |
Table 3c
A | B | C | D | E | F | G | H | |
4 | Percentage change 3 months on previous 3 months | |||||||
5 | Time period | Public new housing | Private new housing | Total new housing | Infrastructure new work | Public other new work | Private industrial new work | Private commercial new work |
6 | Dataset identifier code | MVO6 | MVO7 | MVO8 | MVO9 | MVP2 | MVP3 | MVP4 |
7 | Jun 2010 | 5.6 | 9.8 | 8.8 | 3 | 4.3 | 3.7 | 1.9 |
8 | Jul 2010 | 2 | 5.6 | 4.8 | 0.2 | -0.2 | 9.7 | 3.5 |
9 | Aug 2010 | 5.5 | 4.5 | 4.7 | -2.9 | -2.9 | 24.4 | 5.9 |
10 | Sep 2010 | 11.7 | 7.5 | 8.5 | -6.8 | -3.3 | 16.1 | 5.3 |
Going out of bounds#
A typical error when learning to use tidychef is to go “out of bounds”, this means shifting your selection outside the bounds of the data your’e working with.
i.f if your rightmost populated cell is column ‘F’, if you try and shift a selection into column ‘G’ you’re out of bounds.
First, let’s preview the rightmost populated part of this sheet (column O
) and select a cell.
from tidychef import acquire, preview
from tidychef.selection import XlsxSelectable
from tidychef.direction import right
table: XlsxSelectable = acquire.xlsx.http("https://github.com/mikeAdamss/tidychef/raw/main/tests/fixtures/xlsx/ons-oic.xlsx", tables="Table 3c")
selection = table.excel_ref('O5')
preview(selection, bounded="K4:O10")
Unnamed Selection: 0 |
Table 3c
K | L | M | N | O | |
4 | |||||
5 | Private housing R&M | Total housing R&M | Non housing R&M | All R&M | All work |
6 | N3P2 | N3P3 | N3P4 | N3P5 | N3P6 |
7 | 6.6 | 5.2 | 6.8 | 5.9 | 4.9 |
8 | 6.8 | 6.1 | 2.9 | 4.6 | 3.4 |
9 | 6.5 | 5.4 | 2 | 3.8 | 3.3 |
10 | 6.5 | 3.2 | -2.2 | 0.6 | 1.8 |
Now watch what happens if we try and shift that selection right.
selection.shift(right)
---------------------------------------------------------------------------
OutOfBoundsError Traceback (most recent call last)
Cell In[6], line 1
----> 1 selection.shift(right)
File ~/.pyenv/versions/3.12.11/lib/python3.12/site-packages/tidychef/utils/decorators/dontmutate.py:24, in dontmutate.<locals>.wrapper(self, *args, **kwargs)
21 @wraps(method)
22 def wrapper(self, *args, **kwargs):
23 self = copy.deepcopy(self)
---> 24 return method(self, *args, **kwargs)
File ~/.pyenv/versions/3.12.11/lib/python3.12/site-packages/tidychef/selection/selectable.py:299, in Selectable.shift(self, direction_or_x, possibly_y)
296 found_cells = dfc.matching_xy_cells(self.pcells, wanted_cells)
298 if len(found_cells) == 0 and len(wanted_cells) > 0:
--> 299 raise OutOfBoundsError(
300 "You are attempting to shift your selection "
301 "entirely outside of the boundary of the table."
302 )
304 self.cells = found_cells
305 return self
OutOfBoundsError: You are attempting to shift your selection entirely outside of the boundary of the table.