Объединяйте фреймы данных, используя ближайший час, и заполняйте пропущенные метки времени для определенных объектов - PullRequest
0 голосов
/ 17 января 2019

У меня есть два кадра данных.

Фрейм данных № 1 (df1):

1    object_name     time_epoch_ms      source      data
2    a               1538518822490      source_1     some_data
3    b               1538528822490      source_2     some_data
4    b               1538538822490      source_2     some_data
5    b               1538548822490      source_3     some_data
6    b               1538558822490      source_1     some_data
7    c               1538568822490      source_2     some_data
8    c               1538578822490      source_2     some_data
9    c               1538588822490      source_2     some_data
... etc etc

Фрейм данных № 2 (df2):

1    object_name     time_epoch_ms      new_data
2    a               1538518722490      x
3    b               1538528822490      y
4    b               1538518922490      z
5    b               1538519922490      a
6    b               1538598822490      b
7    c               1538548822490      c
8    c               1538538822490      c
9    c               1538528822490      d
... etc etc

Записи в этих двух таблицах дают информацию об объектах с именами объектов для разных моментов времени.

Я хотел бы объединить эти две таблицы так, чтобы Фрейм данных №2 был дополнен источником, который использовалось для object_name в конкретное время, указанное в Фрейме данных № 1.

Проблема: временные метки в двух таблицах не совпадают точно. Некоторые временные метки, которые существуют в таблице 2, не существуют в таблице 1. Однако они должны примерно соответствовать часу. Некоторые временные метки в таблице 1 отсутствуют, поэтому лучше всего использовать «последние доступные данные».

Есть ли способ выполнить следующие шаги, используя способность слияния панд?

  1. Сопоставлять данные с фреймов данных таким образом, чтобы df2 получал «исходные» данные из df1 на основе object_name и time_stamp, так что time_stamp совпадает до ближайшего часа.
  2. Если данные за определенный час находятся в df2, но не df1, то источник повторяется с последнего доступного часа данные, поэтому он «заполняется» на основе любых данных, существующих для этого объект.
  3. Если объект в df2 не находится в df1, то он получает «ноль»

Мой подход:

В настоящее время я делаю .apply, чтобы получить каждую строку из df2 и найти все метки времени для этого объекта в df1, если они существуют. Затем я возвращаю ближайшее совпадение или ноль.

Мне интересно, есть ли более элегантный способ сделать это, используя функции слияния или объединения панд, но у меня возникают проблемы с пониманием, как использовать их в этом случае и как обрабатывать заполнение данных и сопоставление с учетом часов (без отдельной предварительной обработки, чтобы получить там столбец часа).

1 Ответ

0 голосов
/ 17 января 2019

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

Это немного педантично в отношении того, как настраиваются ваши данные, но MWE:

from io import StringIO
import pandas as pd

df1 = pd.read_table(StringIO("""1    object_name     time_epoch_ms      source      data
2    a               1538518822490      source_1     some_data_1
3    b               1538528822490      source_2     some_data_2
4    b               1538538822490      source_2     some_data_3
5    b               1538548822490      source_3     some_data_4
6    b               1538558822490      source_1     some_data_5
7    c               1538568822490      source_2     some_data_6
8    c               1538578822490      source_2     some_data_7
9    c               1538588822490      source_2     some_data_8
"""), sep=r"\s+", index_col=0)

df2 = pd.read_table(StringIO("""1    object_name     time_epoch_ms      new_data
2    a               1538518722490      x
3    b               1538528822490      y
4    b               1538518922490      z
5    b               1538519922490      a
6    b               1538598822490      b
7    c               1538548822490      c
8    c               1538538822490      c
9    c               1538528822490      d
"""), sep=r"\s+", index_col=0)

pd.merge_asof(
    df2.sort_values(['time_epoch_ms', 'object_name']),
    df1.sort_values(['time_epoch_ms', 'object_name']),
    by="object_name", on="time_epoch_ms",
    direction='forward',
).sort_values(['object_name', 'time_epoch_ms'])

, который возвращает:

  object_name  time_epoch_ms new_data    source         data
0           a  1538518722490        x  source_1  some_data_1
1           b  1538518922490        z  source_2  some_data_2
2           b  1538519922490        a  source_2  some_data_2
3           b  1538528822490        y  source_2  some_data_2
7           b  1538598822490        b       NaN          NaN
4           c  1538528822490        d  source_2  some_data_6
5           c  1538538822490        c  source_2  some_data_6
6           c  1538548822490        c  source_2  some_data_6

См. Pandas-эквивалент SQL-неравенства JOIN для другого примера. Также есть merge_ordered но я не думаю, что это поможет вашему делу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...