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

如何使用纯Pandas/Apply方法替代循环实现按时间戳索引的布尔DataFrame拆分并保存CSV

如何用更简洁的Pandas方法替代循环,将布尔型DataFrame每行的True列名按时间戳保存为CSV?

问题背景

我有一个以时间戳为索引的布尔型DataFrame df,结构如下:

import pandas as pd

data = {
    'x0': [True, True, False],
    'x1': [False, False, True],
    'x2': [True, True, True]
}
df = pd.DataFrame(data, index=pd.to_datetime(['2020-01-01', '2020-01-02', '2020-01-03']))

需求是:将每行中值为True的列名保存为单独的CSV文件,文件名用当前行的时间戳(格式为YYYYMMDD)。预期输出3个CSV文件:

  • 20200101.csv:内容为x0,x2
  • 20200102.csv:内容为x0,x2
  • 20200103.csv:内容为x1,x2

我已经用for循环结合Pandas实现了功能,但代码有点繁琐(在R里用split和lapply几乎一行搞定),现有代码如下:

import numpy as np
for idx, row in df.iterrows():
    tmp = row.replace({False: np.nan}).dropna()
    tmp = pd.DataFrame({"my_col": tmp.index.tolist()})
    file_name = ''.join(str(idx.date()).split('-'))
    tmp.to_csv(f"{file_name}.csv", index=False)

想请教有没有更简洁的实现方式,用纯Pandas、Apply或者类似MapReduce的方法,避免显式的for循环?


解决方案

我来分享几个更简洁的纯Pandas实现方式,完美替代你的循环代码:

方法1:用apply逐行处理(最贴近你的需求风格)

这个方法用apply遍历每一行,直接筛选出True对应的列名并保存,代码非常紧凑:

df.apply(
    lambda row: pd.Series(row[row].index).to_csv(
        f"{row.name.strftime('%Y%m%d')}.csv", 
        index=False, 
        header=False
    ),
    axis=1
)

细节说明:

  • row[row]是Pandas里的实用小技巧:布尔Series作为索引时,会直接筛选出值为True的元素,再取index就是我们要的列名
  • row.name.strftime('%Y%m%d')比手动分割字符串更规范可靠,是专门的时间格式转换方法
  • 把列名列表转成pd.Series后直接调用to_csv,指定index=False和header=False就能得到无多余内容的CSV

方法2:先重塑数据再分组保存(大数据集更高效)

如果你的DataFrame行数很多,逐行apply可能效率一般,这种先转长表再分组的方式会更高效:

# 把宽表转成长表,只保留值为True的记录
stacked_df = df.stack()[lambda s: s].reset_index()

# 按时间戳分组,每组保存为一个CSV
for date, group in stacked_df.groupby('level_0'):
    file_name = date.strftime('%Y%m%d')
    group['level_1'].to_csv(f"{file_name}.csv", index=False, header=False)

细节说明:

  • df.stack()会把原列名转成二级索引,生成一个以(timestamp, column_name)为索引、布尔值为内容的Series
  • [lambda s: s]筛选出所有值为True的行
  • 按原时间戳(level_0)分组后,每组的level_1就是该行对应的列名,直接保存即可

方法3:极致一行式实现(对标R的split+lapply)

如果你追求像R那样的一行代码风格,直接把方法1压缩成一行就行:

df.apply(lambda r: pd.Series(r[r].index).to_csv(f"{r.name.strftime('%Y%m%d')}.csv", index=False, header=False), axis=1)

内容的提问来源于stack exchange,提问作者PyRsquared

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 23:02:40