我正在合并一些有时间索引的数据帧.

import pandas as pd
df1 = pd.DataFrame(['a', 'b', 'c'],
    columns=pd.MultiIndex.from_product([['target'], ['key']]),
    index = [
        '2022-04-15 20:20:20.000000', 
        '2022-04-15 20:20:21.000000', 
        '2022-04-15 20:20:22.000000'],)
df2 = pd.DataFrame(['a2', 'b2', 'c2', 'd2', 'e2'],
    columns=pd.MultiIndex.from_product([['feature2'], ['keys']]),
    index = [
        '2022-04-15 20:20:20.100000', 
        '2022-04-15 20:20:20.500000', 
        '2022-04-15 20:20:20.900000', 
        '2022-04-15 20:20:21.000000', 
        '2022-04-15 20:20:21.100000',],)
df3 = pd.DataFrame(['a3', 'b3', 'c3', 'd3', 'e3'],
    columns=pd.MultiIndex.from_product([['feature3'], ['keys']]),
    index = [
        '2022-04-15 20:20:19.000000', 
        '2022-04-15 20:20:19.200000', 
        '2022-04-15 20:20:20.000000', 
        '2022-04-15 20:20:20.200000', 
        '2022-04-15 20:20:23.100000',],)

然后我使用这个合并过程:

def merge(dfs:list[pd.DataFrame], targetColumn:'str|tuple[str]'):
    from functools import reduce
    if len(dfs) == 0:
        return None
    if len(dfs) == 1:
        return dfs[0]
    for df in dfs:
        df.index = pd.to_datetime(df.index)
    merged = reduce(
        lambda left, right: pd.merge(
            left, 
            right, 
            how='outer',
            left_index=True,
            right_index=True),
        dfs)
    for col in merged.columns:
        if col != targetColumn:
            merged[col] = merged[col].fillna(method='ffill')
    return merged[merged[targetColumn].notna()]

这样地:

merged = merge([df1, df2, df3], targetColumn=('target', 'key'))

这就产生了:

target production

一切都很好.问题是效率——请注意,在merge()过程中,我使用reduce和外部merge将数据帧连接在一起,这会生成一个巨大的临时数据帧,然后被过滤掉.但是如果我的电脑没有足够的内存来处理内存中的巨 Big Data 帧呢?这就是我想要避免的问题.

我想知道是否有办法避免在合并时将数据扩展成一个巨大的数据帧.

当然,常规的旧合并是不够的,因为它只在完全匹配的索引上进行合并,而不是在目标变量观察之前的最新时间索引上进行合并:

df1.merge(df2, how='left', left_index=True, right_index=True)

efficient but bad merge

这类问题得到有效解决了吗?这似乎是一个常见的数据科学问题,因为没有人想将future 的信息泄露到他们的模型中,每个人都有各种各样的输入来合并在一起...

推荐答案

你很幸运:pandas.merge_asof正是你所需要的!

我们使用默认的direction='backward'参数:

"向后"搜索 Select 右数据帧中的最后一行

使用三个示例数据帧:

import pandas as pd
from functools import reduce

# Convert all indexes to datetime
for df in [df1, df2, df3]:
    df.index = pd.to_datetime(df.index)

# Perform as-of merges
res = reduce(lambda left, right:
             pd.merge_asof(left, right, left_index=True, right_index=True),
             [df1, df2, df3])

print(res)

                    target feature2 feature3
                       key     keys     keys
2022-04-15 20:20:20      a      NaN       c3
2022-04-15 20:20:21      b       d2       d3
2022-04-15 20:20:22      c       e2       d3

Python相关问答推荐

预期LP_c_Short实例而不是_ctyles.PyCStructType

来自ARIMA结果的模型方程

如何使用矩阵在sklearn中同时对每个列执行matthews_corrcoef?

如何才能知道Python中2列表中的巧合.顺序很重要,但当1个失败时,其余的不应该失败或是0巧合

使用plotnine和Python构建地块

如何在具有重复数据的pandas中对groupby进行总和,同时保留其他列

根据条件将新值添加到下面的行或下面新创建的行中

当多个值具有相同模式时返回空

Gekko:Spring-Mass系统的参数识别

在Pandas DataFrame操作中用链接替换'方法的更有效方法

为什么默认情况下所有Python类都是可调用的?

如何在UserSerializer中添加显式字段?

将pandas导出到CSV数据,但在此之前,将日期按最小到最大排序

在pandas/python中计数嵌套类别

从旋转的DF查询非NaN值

循环浏览每个客户记录,以获取他们来自的第一个/最后一个渠道

如何在Python请求中组合多个适配器?

用两个字符串构建回文

Beautifulsoup:遍历一个列表,从a到z,并解析数据,以便将其存储在pdf中.

如何在Python 3.9.6和MacOS Sonoma 14.3.1下安装Pyregion