You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据另一DataFrame的索引对DataFrame多列按指定行范围切片?

寻找Pandas中按列保留指定时间切片范围值的最优方法

我正在寻找执行以下操作的最优/最具Python风格的方法(暂未在Stack Overflow上找到类似问题):

对于以日期为索引的df1的每一列,保留df2中定义的(时间)切片范围内的值(df2的keys列对应df1的列名),其余位置填充NaN。

示例数据

df1(日期为索引):

A    B  C
01/01 10  100  1
02/01 20  200  2
03/01 30  300  3
04/01 40  400  4
05/01 50  500  5
06/01 60  600  5

df2(定义各列的时间范围):

keys    start      end
0    A  02/01  04/01
1    B  04/01  06/01
2    C  01/01  04/01

期望处理结果:

A    B    C
01/01 NaN  NaN    1
02/01  20  NaN    2
03/01  30  NaN    3
04/01  40  400    4
05/01 NaN  500  NaN
06/01 NaN  600  NaN

目前我找到的方法是遍历df1的每一列,结合重索引后的df2使用loc,但我不太喜欢在Pandas中使用循环的方式。请问还有其他更优雅的方法吗?谢谢!


解决方案

这里有几种无需显式循环的Pandas风格实现方式,完全贴合Pythonic的代码习惯:

方法1:利用广播创建掩码(高效首选)

先把时间格式统一转为datetime(避免字符串比较的潜在问题),然后通过Pandas的广播机制直接生成布尔掩码,一次性完成过滤:

import pandas as pd

# 转换时间格式(如果原始数据是字符串类型)
df1.index = pd.to_datetime(df1.index, format="%d/%m")
df2[["start", "end"]] = df2[["start", "end"]].apply(pd.to_datetime, format="%d/%m")

# 生成列级时间范围掩码:索引是否在对应列的start和end之间
mask = (df1.index >= df2.set_index("keys")["start"].values) & \
       (df1.index <= df2.set_index("keys")["end"].values)

# 应用掩码,不符合范围的值设为NaN
result = df1.where(mask)

这种方法完全利用Pandas的向量运算特性,没有循环,效率最高,适合处理大规模数据。

方法2:用apply实现列级逻辑(可读性强)

如果追求代码的直观性,可以用df.apply对每列单独处理,逻辑清晰易懂:

# 先把df2转为字典,方便快速查询各列的时间范围
range_dict = df2.set_index("keys")[["start", "end"]].to_dict("index")

# 对每列应用过滤逻辑:仅保留索引在指定时间范围内的值
result = df1.apply(lambda col: col.where(
    (col.index >= range_dict[col.name]["start"]) & 
    (col.index <= range_dict[col.name]["end"])
))

这里的apply是Pandas内置的列级遍历,比手动写for循环更符合Pandas的设计思路,代码也更简洁。

方法3:长格式合并重塑(灵活拓展)

如果后续需要添加更多关联逻辑,可以先把df1转成长格式,和df2合并后过滤,再转回宽格式:

# 将df1转为长格式
df1_long = df1.stack().reset_index(name="value")
df1_long.columns = ["date", "key", "value"]

# 合并df2的时间范围数据
merged = pd.merge(df1_long, df2, left_on="key", right_on="keys")

# 过滤出时间范围内的数据
filtered = merged[(merged["date"] >= merged["start"]) & (merged["date"] <= merged["end"])]

# 转回宽格式得到结果
result = filtered.pivot(index="date", columns="key", values="value")

这种方法的优势是灵活,当需要加入更多列的关联条件时,调整起来会更方便。


内容的提问来源于stack exchange,提问作者DrGorilla.eth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:57:52