Pandas операция слияния для ближайшего отклонения даты +/- 3 дня - PullRequest
0 голосов
/ 07 августа 2020

У меня есть 2 фрейма данных для транзакций:

Слева:

        code        debit       credit         reference        payment date

    1   112133      6,31,964.51 0           MH20181000022319    18.09.2018      
    2   112133      6,29,161.51 0           MH20181000022340    12.09.2018      
    3   112133      2,78,288.51 0           MH20181000022341    27.10.2018      
    4   112133      0           3,13,599.51 MH20181000022502    13.11.2018      
    5   112133      3,16,683.00 0           MH20181000022503    22.07.2018      
    6   112133      3,27,332.00 0           MH20181000022504    02.12.2018  

Справа: -

        code        DR          CR          reference          trans date

    1   112133      7,37,964.51 0           345                 24.09.2018      
    2   112133      0           6,31,964.51 456                 20.09.2018      
    3   112133      1,23,434.00 0           567                 13.05.2018      
    4   112133      3,13,599.51 0           420                 09.03.2018      
    5   112133      0           3,16,683.00 890                 19.01.2018      
    6   112133      3,27,332.00 0           123                 19.01.2018

Я хочу выполнить операцию соединения, используя pandas merge / merge_asof on:

левые столбцы = [«дебет», «дата платежа»]

правые столбцы = [«кредит», «дата перехода»]

проблема в том, что дата платежа не совпадает точно каждый раз, поэтому мне нужно учитывать вариацию +/- 3 дня для данной даты от левой строки к правой строке.

Следовательно, результаты должны в идеале соответствовать 1 левый ряд с двумя правыми.

Я начал ссылаться на merge_asof и merge_ordered, пожалуйста, предложите?

Это было бы очень полезно.

1 Ответ

1 голос
/ 09 августа 2020

При работе с непрерывными сериями (не категорично). Метод, который можно использовать, - превратить его в категориальный, используя pd.cut().

  1. , вычислив даты начала и окончания из слева и справа . создать бункеры каждые 6 дней (почти эквивалент +/- 3 дня)
  2. assign() новый столбец datebin до left и вправо , который классифицирован по датам
  3. объединить по значению и datebin

Большинство код просто анализирует текст, который вы вставили в свой вопрос.

data = """idx        code        debit       credit         reference        payment date
    1   112133      6,31,964.51  0           MH20181000022319    18.09.2018      
    2   112133      6,29,161.51  0           MH20181000022340    12.09.2018      
    3   112133      2,78,288.51  0           MH20181000022341    27.10.2018      
    4   112133      0           3,13,599.51  MH20181000022502    13.11.2018      
    5   112133      3,16,683.00  0           MH20181000022503    22.07.2018      
    6   112133      3,27,332.00  0           MH20181000022504    02.12.2018  """

a = [[t.strip().replace(",", "") for t in re.split("  ",l) if t!=""]  for l in [re.sub("([0-9]+[ ])*(.*)", r"\2", l) for l in data.split("\n")]]
df1 = pd.DataFrame(a[1:], columns=a[0]).drop("idx", axis=1)
df1["payment date"] = pd.to_datetime(df1["payment date"])
data = """idx        code        DR          CR          reference          trans date
    1   112133      7,37,964.51  0           345                 24.09.2018      
    2   112133      0           6,31,964.51  456                 20.09.2018      
    3   112133      1,23,434.00  0           567                 13.05.2018      
    4   112133      3,13,599.51  0           420                 09.03.2018      
    5   112133      0           3,16,683.00  890                 19.01.2018      
    6   112133      3,27,332.00  0           123                 19.01.2018"""
a = [[t.strip().replace(",", "") for t in re.split("  ",l) if t!=""]  for l in [re.sub("([0-9]+[ ])*(.*)", r"\2", l) for l in data.split("\n")]]

df2 = pd.DataFrame(a[1:], columns=a[0]).drop("idx", axis=1)
df2["trans date"] = pd.to_datetime(df2["trans date"])

# NB previous pd.to_datetime()
# get min and max dates from both dataframes, then create a series of bins for every 6 days
# approximates to +/- 3 days
bins = pd.date_range(min(df1["payment date"].min(), df2["trans date"].min()), 
              max(df1["payment date"].max(), df2["trans date"].max()), freq="6D")


dfm = df1.assign(datebin=pd.cut(df1["payment date"], bins=bins))\
    .merge(df2.assign(datebin=pd.cut(df2["trans date"], bins=bins)), 
           left_on=["debit","datebin"], right_on=["CR","datebin"])

вывод

 code_x      debit credit       reference_x payment date                   datebin  code_y DR         CR reference_y trans date
 112133  631964.51      0  MH20181000022319   2018-09-18  (2018-09-16, 2018-09-22]  112133  0  631964.51         456 2018-09-20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...