.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/07_multiple_key_join.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. or to run this example in your browser via JupyterLite or Binder .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_07_multiple_key_join.py: .. _example_multiple_key_join : Spatial join for flight data: Joining across multiple columns ============================================================= Joining tables may be difficult if one entry on one side does not have an exact match on the other side. This problem becomes even more complex when multiple columns are significant for the join. For instance, this is the case for **spatial joins** on two columns, typically longitude and latitude. |joiner| is a scikit-learn compatible transformer that enables performing joins across multiple keys, independantly of the data type (numerical, string or mixed). The following example uses US domestic flights data to illustrate how space and time information from a pool of tables are combined for machine learning. .. |fj| replace:: :func:`~skrub.fuzzy_join` .. |joiner| replace:: :func:`~skrub.Joiner` .. |Pipeline| replace:: :class:`~sklearn.pipeline.Pipeline` .. GENERATED FROM PYTHON SOURCE LINES 32-38 Flight-delays data ------------------ The goal is to predict flight delays. We have a pool of tables that we will use to improve our prediction. The following tables are at our disposal: .. GENERATED FROM PYTHON SOURCE LINES 40-45 The main table: flights dataset ............................... - The `flights` datasets. It contains all US flights date, origin and destination airports and flight time. Here, we consider only flights from 2008. .. GENERATED FROM PYTHON SOURCE LINES 45-55 .. code-block:: Python import pandas as pd from skrub.datasets import fetch_figshare flights = fetch_figshare("41771418").X # Sampling for faster computation. flights = flights.sample(20_000, random_state=1, ignore_index=True) flights.head() .. raw:: html
Year_Month_DayofMonth DayOfWeek CRSDepTime CRSArrTime UniqueCarrier FlightNum TailNum CRSElapsedTime ArrDelay Origin Dest Distance
0 2008-01-13 7 1900-01-01 18:35:00 1900-01-01 20:08:00 CO 150 N17244 213.0 1.0 IAH ONT 1334.0
1 2008-02-21 4 1900-01-01 14:30:00 1900-01-01 16:06:00 NW 807 N590NW 216.0 2.0 MSP SEA 1399.0
2 2008-04-17 4 1900-01-01 09:40:00 1900-01-01 13:15:00 WN 1684 N642WN 155.0 -13.0 SEA DEN 1024.0
3 2008-01-03 4 1900-01-01 08:40:00 1900-01-01 12:03:00 CO 287 N21723 383.0 46.0 EWR SNA 2433.0
4 2008-01-31 4 1900-01-01 12:50:00 1900-01-01 14:10:00 MQ 3157 N848AE 80.0 -14.0 SJC SNA 342.0


.. GENERATED FROM PYTHON SOURCE LINES 56-57 Let us see the arrival delay of the flights in the dataset: .. GENERATED FROM PYTHON SOURCE LINES 57-66 .. code-block:: Python import matplotlib.pyplot as plt import seaborn as sns sns.set_theme(style="ticks") ax = sns.histplot(data=flights, x="ArrDelay") ax.set_yscale("log") plt.show() .. image-sg:: /auto_examples/images/sphx_glr_07_multiple_key_join_001.png :alt: 07 multiple key join :srcset: /auto_examples/images/sphx_glr_07_multiple_key_join_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 67-69 Interesting, most delays are relatively short (<100 min), but there are some very long ones. .. GENERATED FROM PYTHON SOURCE LINES 71-75 Airport data: an auxiliary table from the same database ....................................................... - The ``airports`` dataset, with information such as their name and location (longitude, latitude). .. GENERATED FROM PYTHON SOURCE LINES 75-79 .. code-block:: Python airports = fetch_figshare("41710257").X airports.head() .. raw:: html
iata airport city state country lat long
0 00M Thigpen Bay Springs MS USA 31.953765 -89.234505
1 00R Livingston Municipal Livingston TX USA 30.685861 -95.017928
2 00V Meadow Lake Colorado Springs CO USA 38.945749 -104.569893
3 01G Perry-Warsaw Perry NY USA 42.741347 -78.052081
4 01J Hilliard Airpark Hilliard FL USA 30.688012 -81.905944


.. GENERATED FROM PYTHON SOURCE LINES 80-85 Weather data: auxiliary tables from external sources .................................................... - The ``weather`` table. Weather details by measurement station. Both tables are from the Global Historical Climatology Network. Here, we consider only weather measurements from 2008. .. GENERATED FROM PYTHON SOURCE LINES 85-91 .. code-block:: Python weather = fetch_figshare("41771457").X # Sampling for faster computation. weather = weather.sample(100_000, random_state=1, ignore_index=True) weather.head() .. raw:: html
ID YEAR/MONTH/DAY TMAX PRCP SNOW
0 ASN00041037 2008-06-18 NaN 0.0 NaN
1 USC00164696 2008-01-04 39.0 0.0 0.0
2 US1ILSP0008 2008-08-19 NaN 0.0 0.0
3 USC00164931 2008-10-05 NaN 0.0 0.0
4 NOE00111309 2008-08-18 NaN 0.0 NaN


.. GENERATED FROM PYTHON SOURCE LINES 92-94 - The ``stations`` dataset. Provides location of all the weather measurement stations in the US. .. GENERATED FROM PYTHON SOURCE LINES 94-98 .. code-block:: Python stations = fetch_figshare("41710524").X stations.head() .. raw:: html
ID LATITUDE LONGITUDE ELEVATION STATE NAME GSN FLAG HCN/CRN FLAG WMO ID
0 ACW00011604 17.1167 -61.7833 10.1 ST JOHNS COOLIDGE FLD None None NaN NaN
1 ACW00011647 17.1333 -61.7833 19.2 ST JOHNS None None NaN NaN
2 AE000041196 25.3330 55.5170 34.0 SHARJAH INTER. AIRP None GSN 41196.0 NaN
3 AEM00041194 25.2550 55.3640 10.4 DUBAI INTL None None 41194.0 NaN
4 AEM00041217 24.4330 54.6510 26.8 ABU DHABI INTL None None 41217.0 NaN


.. GENERATED FROM PYTHON SOURCE LINES 99-102 Joining: feature augmentation across tables ------------------------------------------- First we join the stations with weather on the ID (exact join): .. GENERATED FROM PYTHON SOURCE LINES 102-106 .. code-block:: Python aux = pd.merge(stations, weather, on="ID") aux.head() .. raw:: html
ID LATITUDE LONGITUDE ELEVATION STATE NAME GSN FLAG HCN/CRN FLAG WMO ID YEAR/MONTH/DAY TMAX PRCP SNOW
0 AE000041196 25.333 55.517 34.0 SHARJAH INTER. AIRP None GSN 41196.0 NaN 2008-08-15 422.0 0.0 NaN
1 AE000041196 25.333 55.517 34.0 SHARJAH INTER. AIRP None GSN 41196.0 NaN 2008-05-08 374.0 0.0 NaN
2 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-04-04 288.0 0.0 NaN
3 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-05-21 365.0 0.0 NaN
4 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-01-21 221.0 0.0 NaN


.. GENERATED FROM PYTHON SOURCE LINES 107-109 Then we join this table with the airports so that we get all auxilliary tables into one. .. GENERATED FROM PYTHON SOURCE LINES 109-118 .. code-block:: Python from skrub import Joiner joiner = Joiner(airports, aux_key=["lat", "long"], main_key=["LATITUDE", "LONGITUDE"]) aux_augmented = joiner.fit_transform(aux) aux_augmented.head() .. raw:: html
ID LATITUDE LONGITUDE ELEVATION STATE NAME GSN FLAG HCN/CRN FLAG WMO ID YEAR/MONTH/DAY TMAX PRCP SNOW iata airport city state country lat long skrub_Joiner_distance skrub_Joiner_rescaled_distance skrub_Joiner_match_accepted
0 AE000041196 25.333 55.517 34.0 SHARJAH INTER. AIRP None GSN 41196.0 NaN 2008-08-15 422.0 0.0 NaN ROP Prachinburi None None Thailand 14.078333 101.378334 2.418438 3.314383 True
1 AE000041196 25.333 55.517 34.0 SHARJAH INTER. AIRP None GSN 41196.0 NaN 2008-05-08 374.0 0.0 NaN ROP Prachinburi None None Thailand 14.078333 101.378334 2.418438 3.314383 True
2 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-04-04 288.0 0.0 NaN ROP Prachinburi None None Thailand 14.078333 101.378334 2.418781 3.314853 True
3 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-05-21 365.0 0.0 NaN ROP Prachinburi None None Thailand 14.078333 101.378334 2.418781 3.314853 True
4 AEM00041194 25.255 55.364 10.4 DUBAI INTL None None 41194.0 NaN 2008-01-21 221.0 0.0 NaN ROP Prachinburi None None Thailand 14.078333 101.378334 2.418781 3.314853 True


.. GENERATED FROM PYTHON SOURCE LINES 119-121 Joining airports with flights data: Let's instanciate another multiple key joiner on the date and the airport: .. GENERATED FROM PYTHON SOURCE LINES 121-130 .. code-block:: Python joiner = Joiner( aux_augmented, aux_key=["YEAR/MONTH/DAY", "iata"], main_key=["Year_Month_DayofMonth", "Origin"], ) flights.drop(columns=["TailNum", "FlightNum"]) .. raw:: html
Year_Month_DayofMonth DayOfWeek CRSDepTime CRSArrTime UniqueCarrier CRSElapsedTime ArrDelay Origin Dest Distance
0 2008-01-13 7 1900-01-01 18:35:00 1900-01-01 20:08:00 CO 213.0 1.0 IAH ONT 1334.0
1 2008-02-21 4 1900-01-01 14:30:00 1900-01-01 16:06:00 NW 216.0 2.0 MSP SEA 1399.0
2 2008-04-17 4 1900-01-01 09:40:00 1900-01-01 13:15:00 WN 155.0 -13.0 SEA DEN 1024.0
3 2008-01-03 4 1900-01-01 08:40:00 1900-01-01 12:03:00 CO 383.0 46.0 EWR SNA 2433.0
4 2008-01-31 4 1900-01-01 12:50:00 1900-01-01 14:10:00 MQ 80.0 -14.0 SJC SNA 342.0
... ... ... ... ... ... ... ... ... ... ...
19995 2008-01-14 1 1900-01-01 09:50:00 1900-01-01 11:45:00 WN 115.0 -7.0 SMF SEA 605.0
19996 2008-03-19 3 1900-01-01 13:55:00 1900-01-01 18:40:00 AA 165.0 -27.0 LAS DFW 1055.0
19997 2008-03-15 6 1900-01-01 12:00:00 1900-01-01 18:50:00 WN 230.0 -29.0 PHX PIT 1813.0
19998 2008-02-27 3 1900-01-01 07:20:00 1900-01-01 09:00:00 MQ 100.0 NaN XNA ORD 522.0
19999 2008-03-04 2 1900-01-01 06:20:00 1900-01-01 08:01:00 9E 101.0 -8.0 IAH MEM 469.0

20000 rows × 10 columns



.. GENERATED FROM PYTHON SOURCE LINES 131-136 Training data is then passed through a |Pipeline|: - We will combine all the information from our pool of tables into "flights", our main table. - We will use this main table to model the prediction of flight delay. .. GENERATED FROM PYTHON SOURCE LINES 136-147 .. code-block:: Python from sklearn.ensemble import HistGradientBoostingClassifier from sklearn.pipeline import make_pipeline from skrub import TableVectorizer tv = TableVectorizer() hgb = HistGradientBoostingClassifier() pipeline_hgb = make_pipeline(joiner, tv, hgb) .. GENERATED FROM PYTHON SOURCE LINES 148-149 We isolate our target variable and remove useless ID variables: .. GENERATED FROM PYTHON SOURCE LINES 149-153 .. code-block:: Python y = flights["ArrDelay"] X = flights.drop(columns=["ArrDelay"]) .. GENERATED FROM PYTHON SOURCE LINES 154-160 We want to frame this as a classification problem: suppose that your company is obliged to reimburse the ticket price if the flight is delayed. We have a binary classification problem: the flight was delayed (1) or not (0). .. GENERATED FROM PYTHON SOURCE LINES 160-164 .. code-block:: Python y = (y > 0).astype(int) y.value_counts() .. rst-class:: sphx-glr-script-out .. code-block:: none ArrDelay 0 10686 1 9314 Name: count, dtype: int64 .. GENERATED FROM PYTHON SOURCE LINES 165-166 The results: .. GENERATED FROM PYTHON SOURCE LINES 166-172 .. code-block:: Python from sklearn.model_selection import cross_val_score scores = cross_val_score(pipeline_hgb, X, y) scores.mean() .. rst-class:: sphx-glr-script-out .. code-block:: none /home/circleci/project/.pixi/envs/doc/lib/python3.12/site-packages/sklearn/preprocessing/_encoders.py:242: UserWarning: Found unknown categories in columns [0] during transform. These unknown categories will be encoded as all zeros warnings.warn( /home/circleci/project/.pixi/envs/doc/lib/python3.12/site-packages/sklearn/preprocessing/_encoders.py:242: UserWarning: Found unknown categories in columns [0] during transform. These unknown categories will be encoded as all zeros warnings.warn( /home/circleci/project/.pixi/envs/doc/lib/python3.12/site-packages/sklearn/preprocessing/_encoders.py:242: UserWarning: Found unknown categories in columns [0] during transform. These unknown categories will be encoded as all zeros warnings.warn( np.float64(0.58435) .. GENERATED FROM PYTHON SOURCE LINES 173-181 Conclusion ---------- In this example, we have combined multiple tables with complex joins on imprecise and multiple-key correspondences. This is made easy by skrub's |Joiner| transformer. Our final cross-validated accuracy score is 0.58. .. rst-class:: sphx-glr-timing **Total running time of the script:** (6 minutes 56.410 seconds) .. _sphx_glr_download_auto_examples_07_multiple_key_join.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/skrub-data/skrub/main?urlpath=lab/tree/notebooks/auto_examples/07_multiple_key_join.ipynb :alt: Launch binder :width: 150 px .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../lite/lab/index.html?path=auto_examples/07_multiple_key_join.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 07_multiple_key_join.ipynb <07_multiple_key_join.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 07_multiple_key_join.py <07_multiple_key_join.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 07_multiple_key_join.zip <07_multiple_key_join.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_