Как объединить две таблицы в пандах по времени с задержкой - PullRequest
0 голосов
/ 04 марта 2019

У меня фактически есть два CSV-файла, df1 и df2.

Когда я использую команду: df1 = pd.read_csv ("путь", index_col = "созданный_кат", parse_dates = ["созданный_кат"])

Я получаю:

                      index   likes    ...      user_screen_name  sentiment
created_at                            ...
2019-02-27 05:36:29      0   94574    ...       realDonaldTrump   positive
2019-02-27 05:31:21      1   61666    ...       realDonaldTrump   negative
2019-02-26 18:08:14      2  151844    ...       realDonaldTrump   positive
2019-02-26 04:50:37      3  184597    ...       realDonaldTrump   positive
2019-02-26 04:50:36      4  181641    ...       realDonaldTrump   negative
       ...             ...    ...     ...           ...             ...

Когда я использую команду:

df2=pd.read_csv("path",index_col="created_at",parse_dates=["created_at"])

Я получаю:

                     Unnamed: 0    Close     Open  Volume     Day
created_at
2019-03-01 00:47:00           0  2784.49  2784.49     NaN  STABLE
2019-03-01 00:21:00           1  2784.49  2784.49     NaN  STABLE
2019-03-01 00:20:00           2  2784.49  2784.49     NaN  STABLE
2019-03-01 00:19:00           3  2784.49  2784.49     NaN  STABLE
2019-03-01 00:18:00           4  2784.49  2784.49     NaN  STABLE
2019-03-01 00:17:00           5  2784.49  2784.49     NaN  STABLE
        ...                 ...    ...      ...       ...    ...

Как вы знаете, когдавы используете команду:

df3=df1.join(df2)

Вы объедините две таблицы на основе индекса «create_at» с точной датой и временем в этих двух таблицах.

Но я хотел бы иметьрезультат с задержкой, например, 2 мин.

Например, вместо:

file df1                   file df2
created_at                 created_at
2019-02-27 05:36:29        2019-02-27 05:36:29

Я бы хотел, чтобы две таблицы соединились следующим образом:

file df1                   file df2
created_at                 created_at
2019-02-27 05:36:29        2019-02-27 05:38:29

Для моих данных важно, чтобы время df1 было до df2.Я имею в виду, что важно, чтобы событие df1 было до df2.

1 Ответ

0 голосов
/ 04 марта 2019

Для небольших фреймов данных Объединение двух фреймов данных на основе даты между двумя другими датами без общего столбца дает хорошее решение.Просто он использует декартово произведение обоих фреймов данных и не будет хорошо масштабироваться с большими фреймами данных.

Возможной оптимизацией будет добавление округленных столбцов даты и времени к фреймам данных и присоединение к ним.эти столбцы.Поскольку объединение намного более эффективно, чем декартово произведение, выигрыш в памяти и времени выполнения должен быть заметен.

То, что вы хотите (псевдокод здесь):

df1.created_at <= df2.created_at and df2.created_at - df1.created_at <= 2mins

Я бы добавилв обоих фреймах данных столбец ref, определенный как (все еще псевдокод): created_at - (created_at.minute % 2)

Строки в обоих фреймах данных имеют одинаковое значение ссылки, даты должны быть на расстоянии менее 4 минут.Но это не выберет все ожидаемые случаи, потому что даты могут быть ближе, чем 2 минуты и попадают в 2 разных слота.Чтобы справиться с этим, я предлагаю иметь столбец ref2 в df1, определенный как ref1 + 2minutes, и выполнить второе объединение на df1.ref == df1.ref2.Этого будет достаточно, потому что вы хотите, чтобы событие df1 было раньше df2, иначе нам понадобится 3-й столбец ref3 = ref1 - 2minutes.

Затем, как и в указанном ответе, мы можем выбрать строки, фактически соответствующие требованию, исвяжитесь с двумя соединенными фреймами данных.

Код Pandas может быть:

# create auxilliary columns
df1['ref'] = df1.index - pd.to_timedelta(df1.index.minute % 2, unit='m')
df1['ref2'] = df1.ref + pd.Timedelta(minutes=2)

df2['ref'] = df2.index - pd.to_timedelta(df2.index.minute % 2, unit='m')
df2.index.name = 'created_at_2'
df2 = df2.reset_index().set_index('ref')

# join on ref and select the relevant lines
x1 = df1.join(df2, on='ref', how='inner')
x1 = x1.loc[(x1.index <= x1.created_at_2)
            & (x1.created_at_2 - x1.index <= pd.Timedelta(minutes=2))]

# join on ref2 and select the relevant lines
x2 = df1.join(df2, on='ref2', how='inner')
x2 = x2.loc[(x2.index <= x2.created_at_2)
            & (x2.created_at_2 - x2.index <= pd.Timedelta(minutes=1))]

# concatenate the partial result and clean the resulting dataframe
merged = pd.concat([x1, x2]).drop(columns=['ref', 'ref2'])
merged.index.name = 'created_at'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...