【问题标题】:Join Data Frames Using Closest Hour and Fill in Missing Time Stamps for Particular Objects使用最近时间连接数据框并为特定对象填充缺失的时间戳
【发布时间】:2023-03-22 21:28:02
【问题描述】:

我有两个数据框。

数据帧 #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

这两个表中的条目提供了有关不同时间点的对象名称的对象的信息。

我想组合这两个表,以便在数据框 #1 中指定的特定时间使用 object_name 使用的源来扩充数据框 #2。

问题:两个表中的时间戳不完全匹配。表 2 中存在的一些时间戳在表 1 中不存在。但是,它们应该大致对应于小时。缺少表 1 中的一些时间戳,因此最好使用“最后可用数据”。

有没有办法使用 pandas 的合并功能来执行以下步骤?

  1. 匹配数据帧中的数据,以便 df2 从中获取“源”数据 df1 基于 object_name 和 time_stamp 使得 time_stamp 匹配 到最近的时间。
  2. 如果特定小时的数据在 df2 中,但 不是 df1,然后从最后一个可用小时重试源 数据,因此它是根据存在的任何数据“填充”的 对象。
  3. 如果 df2 中的对象不在 df1 中,则它得到一个“null”

我的做法:

我目前使用 .apply 从 df2 获取每一行,并在 df1 中查找该对象的所有时间戳(如果存在)。然后,我返回最接近的匹配项或 null。

我想知道是否有更优雅的方法可以使用 pandas 的合并或连接功能来执行此操作,但我无法理解在这种情况下如何使用它们以及如何处理填充数据并根据小时进行匹配(无需进行单独的预处理以获得小时列)。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    一般来说,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 equivalent of SQL non-equi JOIN。还有merge_ordered,但我认为这对你的情况没有帮助。

    【讨论】:

      猜你喜欢
      • 2017-05-12
      • 1970-01-01
      • 2021-06-13
      • 2020-09-13
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      相关资源
      最近更新 更多