polars.DataFrame.join_asof
-
Выполняет асоф-соединение.
Это похоже на левое соединение, за исключением того, что сопоставление выполняется по ближайшему ключу, а не по совпадающим ключам.
Оба DataFrame должны быть отсортированы по ключу
on(внутри каждой группыby, если она указана).Для каждой строки левого DataFrame:
- Поиск «назад» выбирает последнюю строку правого DataFrame, ключ ‘on’ которой меньше или равен ключу левого DataFrame.
- Поиск «вперёд» выбирает первую строку правого DataFrame, ключ ‘on’ которой больше или равен ключу левого DataFrame.
- Поиск «ближайшего значения» выбирает последнюю строку правого DataFrame, значение которой ближе всего к ключу левого DataFrame. Строковые ключи в настоящее время не поддерживаются для поиска ближайшего значения.
По умолчанию используется поиск «назад».
- Параметры:
-
- other
-
Ленивый DataFrame для соединения.
- left_on
-
Столбец соединения левого DataFrame.
- right_on
-
Столбец соединения правого DataFrame.
- on
-
Столбец соединения обоих DataFrame. Если задан,
left_onиright_onдолжны иметь значение None. - by_left
-
Сначала выполнить соединение по этим столбцам, затем асоф-соединение
- by_right
-
Сначала выполнить соединение по этим столбцам, затем асоф-соединение
- by
-
Сначала выполнить соединение по этим столбцам, затем асоф-соединение
-
strategy{‘backward’, ‘forward’, ‘nearest’} -
Стратегия соединения.
- suffix
-
Суффикс, добавляемый к столбцам с повторяющимся именем.
- tolerance
-
Числовой допуск. Если задать это значение, соединение будет выполнено, только если расстояние между близкими ключами не превышает его. Если асоф-соединение выполняется по столбцам типа “Date”, “Datetime”, “Duration” или “Time”, используйте объект datetime.timedelta или строку в следующем формате:
- 1ns (1 наносекунда)
- 1us (1 микросекунда)
- 1ms (1 миллисекунда)
- 1s (1 секунда)
- 1m (1 минута)
- 1h (1 час)
- 1d (1 календарный день)
- 1w (1 календарная неделя)
- 1mo (1 календарный месяц)
- 1q (1 календарный квартал)
- 1y (1 календарный год)
Или объедините их: “3d12h4m25s” # 3 дня, 12 часов, 4 минуты и 25 секунд
Под «календарным днём» подразумевается соответствующее время следующего дня (который может длиться не 24 часа из-за перехода на летнее время; в неоднозначных случаях мы следуем RFC-5545 и сохраняем признак DST fold исходного объекта datetime). Аналогично для «календарной недели», «календарного месяца», «календарного квартала» и «календарного года».
- allow_parallel
-
Разрешить физическому плану при необходимости параллельно вычислять оба DataFrame вплоть до этапа соединения.
- force_parallel
-
Принудительно выполнять вычисления обоих DataFrame физическим планом параллельно вплоть до этапа соединения.
- coalesce
-
Поведение объединения (слияние столбцов
on/left_on/right_on):- True: Всегда объединять столбцы соединения.
- False: Никогда не объединять столбцы соединения.
Обратите внимание: соединение по любым выражениям, кроме
col, отключает объединение. - allow_exact_matches
-
Допускаются ли точные совпадения в условиях соединения.
-
-
If True, allow matching with the same on value -
(то есть «меньше или равно» / «больше или равно»)
-
-
-
If False, don’t match the same on value -
(то есть строго «меньше» / строго «больше»).
-
-
- check_sortedness
-
Проверять сортировку ключей асоф-соединения. Если ключи не отсортированы, Polars выдаст ошибку. В настоящее время движок
in-memoryне может проверить сортировку, если указаны группы ‘by’. Движокstreamingпроверяет сортировку только обрабатываемых им строк.
См. также
Примеры
>>> from datetime import date >>> gdp = pl.DataFrame( ... { ... "date": pl.date_range( ... date(2016, 1, 1), ... date(2020, 1, 1), ... "1y", ... eager=True, ... ), ... "gdp": [4164, 4411, 4566, 4696, 4827], ... } ... ) >>> gdp shape: (5, 2) ┌────────────┬──────┐ │ date ┆ gdp │ │ --- ┆ --- │ │ date ┆ i64 │ ╞════════════╪══════╡ │ 2016-01-01 ┆ 4164 │ │ 2017-01-01 ┆ 4411 │ │ 2018-01-01 ┆ 4566 │ │ 2019-01-01 ┆ 4696 │ │ 2020-01-01 ┆ 4827 │ └────────────┴──────┘>>> population = pl.DataFrame( ... { ... "date": [date(2016, 3, 1), date(2018, 8, 1), date(2019, 1, 1)], ... "population": [82.19, 82.66, 83.12], ... } ... ).sort("date") >>> population shape: (3, 2) ┌────────────┬────────────┐ │ date ┆ population │ │ --- ┆ --- │ │ date ┆ f64 │ ╞════════════╪════════════╡ │ 2016-03-01 ┆ 82.19 │ │ 2018-08-01 ┆ 82.66 │ │ 2019-01-01 ┆ 83.12 │ └────────────┴────────────┘Обратите внимание, что даты не совсем совпадают. Если объединить их с помощью
join_asofиstrategy='backward', каждая дата изpopulation, для которой нет точного совпадения, будет сопоставлена с ближайшей более ранней датой изgdp:>>> population.join_asof(gdp, on="date", strategy="backward") shape: (3, 3) ┌────────────┬────────────┬──────┐ │ date ┆ population ┆ gdp │ │ --- ┆ --- ┆ --- │ │ date ┆ f64 ┆ i64 │ ╞════════════╪════════════╪══════╡ │ 2016-03-01 ┆ 82.19 ┆ 4164 │ │ 2018-08-01 ┆ 82.66 ┆ 4566 │ │ 2019-01-01 ┆ 83.12 ┆ 4696 │ └────────────┴────────────┴──────┘
Обратите внимание:
- дата
2016-03-01изpopulationсопоставляется с2016-01-01изgdp; - дата
2018-08-01изpopulationсопоставляется с2018-01-01изgdp.
Это можно проверить, передав
coalesce=False:>>> population.join_asof(gdp, on="date", strategy="backward", coalesce=False) shape: (3, 4) ┌────────────┬────────────┬────────────┬──────┐ │ date ┆ population ┆ date_right ┆ gdp │ │ --- ┆ --- ┆ --- ┆ --- │ │ date ┆ f64 ┆ date ┆ i64 │ ╞════════════╪════════════╪════════════╪══════╡ │ 2016-03-01 ┆ 82.19 ┆ 2016-01-01 ┆ 4164 │ │ 2018-08-01 ┆ 82.66 ┆ 2018-01-01 ┆ 4566 │ │ 2019-01-01 ┆ 83.12 ┆ 2019-01-01 ┆ 4696 │ └────────────┴────────────┴────────────┴──────┘
Если вместо этого использовать
strategy='forward', каждая дата изpopulation, для которой нет точного совпадения, будет сопоставлена с ближайшей более поздней датой изgdp:>>> population.join_asof(gdp, on="date", strategy="forward") shape: (3, 3) ┌────────────┬────────────┬──────┐ │ date ┆ population ┆ gdp │ │ --- ┆ --- ┆ --- │ │ date ┆ f64 ┆ i64 │ ╞════════════╪════════════╪══════╡ │ 2016-03-01 ┆ 82.19 ┆ 4411 │ │ 2018-08-01 ┆ 82.66 ┆ 4696 │ │ 2019-01-01 ┆ 83.12 ┆ 4696 │ └────────────┴────────────┴──────┘
Обратите внимание:
- дата
2016-03-01изpopulationсопоставляется с2017-01-01изgdp; - дата
2018-08-01изpopulationсопоставляется с2019-01-01изgdp.
Наконец,
strategy='nearest'даёт результат, сочетающий два предыдущих варианта: каждая дата изpopulation, для которой нет точного совпадения, сопоставляется с ближайшей датой изgdpнезависимо от того, является ли она более ранней или более поздней:>>> population.join_asof(gdp, on="date", strategy="nearest") shape: (3, 3) ┌────────────┬────────────┬──────┐ │ date ┆ population ┆ gdp │ │ --- ┆ --- ┆ --- │ │ date ┆ f64 ┆ i64 │ ╞════════════╪════════════╪══════╡ │ 2016-03-01 ┆ 82.19 ┆ 4164 │ │ 2018-08-01 ┆ 82.66 ┆ 4696 │ │ 2019-01-01 ┆ 83.12 ┆ 4696 │ └────────────┴────────────┴──────┘
Обратите внимание:
- дата
2016-03-01изpopulationсопоставляется с2016-01-01изgdp; - дата
2018-08-01изpopulationсопоставляется с2019-01-01изgdp.
Аргумент
byпозволяет сначала выполнить соединение по другому столбцу, а затем асоф-соединение. В этом примере сначала выполняется соединение поcountry, а затем асоф-соединение по дате, как показано выше.>>> gdp_dates = pl.date_range( # fmt: skip ... date(2016, 1, 1), date(2020, 1, 1), "1y", eager=True ... ) >>> gdp2 = pl.DataFrame( ... { ... "country": ["Germany"] * 5 + ["Netherlands"] * 5, ... "date": pl.concat([gdp_dates, gdp_dates]), ... "gdp": [4164, 4411, 4566, 4696, 4827, 784, 833, 914, 910, 909], ... } ... ).sort("country", "date") >>> >>> gdp2 shape: (10, 3) ┌─────────────┬────────────┬──────┐ │ country ┆ date ┆ gdp │ │ --- ┆ --- ┆ --- │ │ str ┆ date ┆ i64 │ ╞═════════════╪════════════╪══════╡ │ Germany ┆ 2016-01-01 ┆ 4164 │ │ Germany ┆ 2017-01-01 ┆ 4411 │ │ Germany ┆ 2018-01-01 ┆ 4566 │ │ Germany ┆ 2019-01-01 ┆ 4696 │ │ Germany ┆ 2020-01-01 ┆ 4827 │ │ Netherlands ┆ 2016-01-01 ┆ 784 │ │ Netherlands ┆ 2017-01-01 ┆ 833 │ │ Netherlands ┆ 2018-01-01 ┆ 914 │ │ Netherlands ┆ 2019-01-01 ┆ 910 │ │ Netherlands ┆ 2020-01-01 ┆ 909 │ └─────────────┴────────────┴──────┘ >>> pop2 = pl.DataFrame( ... { ... "country": ["Germany"] * 3 + ["Netherlands"] * 3, ... "date": [ ... date(2016, 3, 1), ... date(2018, 8, 1), ... date(2019, 1, 1), ... date(2016, 3, 1), ... date(2018, 8, 1), ... date(2019, 1, 1), ... ], ... "population": [82.19, 82.66, 83.12, 17.11, 17.32, 17.40], ... } ... ).sort("country", "date") >>> >>> pop2 shape: (6, 3) ┌─────────────┬────────────┬────────────┐ │ country ┆ date ┆ population │ │ --- ┆ --- ┆ --- │ │ str ┆ date ┆ f64 │ ╞═════════════╪════════════╪════════════╡ │ Germany ┆ 2016-03-01 ┆ 82.19 │ │ Germany ┆ 2018-08-01 ┆ 82.66 │ │ Germany ┆ 2019-01-01 ┆ 83.12 │ │ Netherlands ┆ 2016-03-01 ┆ 17.11 │ │ Netherlands ┆ 2018-08-01 ┆ 17.32 │ │ Netherlands ┆ 2019-01-01 ┆ 17.4 │ └─────────────┴────────────┴────────────┘ >>> pop2.join_asof(gdp2, by="country", on="date", strategy="nearest") shape: (6, 4) ┌─────────────┬────────────┬────────────┬──────┐ │ country ┆ date ┆ population ┆ gdp │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ date ┆ f64 ┆ i64 │ ╞═════════════╪════════════╪════════════╪══════╡ │ Germany ┆ 2016-03-01 ┆ 82.19 ┆ 4164 │ │ Germany ┆ 2018-08-01 ┆ 82.66 ┆ 4696 │ │ Germany ┆ 2019-01-01 ┆ 83.12 ┆ 4696 │ │ Netherlands ┆ 2016-03-01 ┆ 17.11 ┆ 784 │ │ Netherlands ┆ 2018-08-01 ┆ 17.32 ┆ 910 │ │ Netherlands ┆ 2019-01-01 ┆ 17.4 ┆ 910 │ └─────────────┴────────────┴────────────┴──────┘
DataFrame.join_asof(
other: DataFrame,
*,
left_on: str | None | Expr = None,
right_on: str | None | Expr = None,
on: str | None | Expr = None,
by_left: str | Sequence[str] | None = None,
by_right: str | Sequence[str] | None = None,
by: str | Sequence[str] | None = None,
strategy: AsofJoinStrategy = 'backward',
suffix: str = '_right',
tolerance: str | int | float | timedelta | None = None,
allow_parallel: bool = True,
force_parallel: bool = False,
coalesce: bool = True,
allow_exact_matches: bool = True,
check_sortedness: bool = True,
) → DataFrame
© 2020 Ritchie Vink
© 2022 Polars contributors
Licensed under the MIT License.
https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join_asof.html