以下代码,看下问题出在哪里

 想用pandas实现每日告警统计,输出每日的告警,编写了以下代码,输出一天没有问题,但是想输出多天的时候,涉及到在excel中输入多个子表,想到的办法是用pandas的ExcelWriter函数和while循环实现,其中有一个值在每一个表格中都不一样,涉及到在遍历索引的时候,给对应的单元格赋值,第一个写入的表格都是正常的,但是在写入第二个和后续的表格时候,就发下写入的时间差还是第一个表格的时间差,但是如果在赋值语句最后加入print()语句,写入的就是正确的结果,其他都没有变化,想问下这个是怎么回事?

未加print()语句输出的结果,两个表格都是一样的,但是不符合设计;

加入print()语句输出的结果,两个表格就不一样了:

这个是程序的问题,还是我用的方法不对?

(ps,上传不了文件,没办法把源数据上传)

import os.path
import pandas as pd
import time


def get_all_excel(dir):  # 定义一个函数,函数名称get_all_excel,需要传入一个目录地址
    """将文件夹中所有excel文件合并成一个DataFrame,并返回"""
    filename_list = []
    for root, dirs, files in os.walk(dir):  # 遍历目录,获取文件名称,目录地址
        # print(root, dirs, files)
        for file in files:
            if file.endswith('xlsx'):
                # print(root+'/'+file )
                filename_list.append(root + '/' + file)  # 将excel拼接成完成的地址,并加入到路径列表中
    dr = pd.DataFrame()
    for filename in filename_list:  # 遍历excel路径列表,将其合并成一个DataFrame
        df1 = pd.read_excel(filename)  # 读取excel
        dr = dr.append(df1, ignore_index=True)  # 将excel拼接到DataFrame里面,并按照新的索引
    return dr


def del_colunms(df):
    """删除掉不用的列"""
    del df['告警ID']
    del df['业务系统']
    del df['资源IP']
    del df['告警信息']
    del df['告警状态']
    del df['恢复来源']
    del df['处理状态']
    del df['资源组']
    del df['指标名称']
    del df['接收人']
    del df['通知状态']
    del df['最近一次调度结果']
    del df['已新建疑似故障']
    del df['调度历史']
    del df['产生原因']
    del df['处理记录']
    del df['关闭时间']
    del df['响应用户']
    del df['响应时间']
    del df['关闭用户']
    del df['处于维护期']
    df.dropna(axis=1, how='all', inplace=True)  # 删除空列


def calculat_time(df):
    """计算最后告警时间和开始告警时间之间的差值"""
    df['首次告警时间'] = pd.to_datetime(df['首次告警时间'])  # 转换为时间类型
    df['最后告警时间'] = pd.to_datetime(df['最后告警时间'])
    if '时间差' in list(df):  # 返回df的columns标签列表,查询‘时间差’是否在列表里面,如果在里面,删除掉重新插入,如果不在里面,直接建立‘时间差’列
        del df['时间差']
        df.insert(3, column='时间差', value=pd.Timedelta('0 hours'))  # 插入一个列,作为后面两个时间计算值的承载
    else:
        df.insert(3, column='时间差', value=pd.Timedelta('0 hours'))  # 插入一个列,作为后面两个时间计算值的承载


def clear_data(df):
    """数据清理,将不需要的数据清理掉"""
    row_indexs = []
    for row_index, row in df.iterrows():
        if '0天0时' in row['持续时间'] or 'MV' not in row['资源名称'] or '紧急' not in row['告警级别'] or \
                '0天1时' in row['持续时间'] or '0天2时' in row['持续时间'] or '0天3时' in row['持续时间']:  # 将持续时间里面小于1小时的筛选出来
            row_indexs.append(row_index)
    df.drop(row_indexs, inplace=True)  # 删除不需要的数据
    df.index = range(0, len(df))  # 重新建立索引


def calau_data(df):
    """接受一个DataFrame,返回前一天的告警信息的索引,"""
    current_time = time.strftime('%Y-%m-%d', time.localtime())  # 返回当天的时间
    end_data = pd.Timestamp(current_time)  # 根据当天时间生产当天0点的时间类
    start_data = pd.Timestamp(current_time) - pd.Timedelta('1 days')  # 根据当天时间生产当天0点的时间类
    indexs = []  # 定义一个空列表
    for index, start_time, end_time in zip(df.index, df['首次告警时间'], df['最后告警时间']):
        if end_time > start_data and start_time < end_data:
            indexs.append(index)
    for i in indexs:
        standing = end_data - df['首次告警时间'].at[i]  # 计算出来持续时间
        if standing.days == 0:
            standing = str(standing)  # 将时间类型转成字符串
            if standing[7] == '0':  # 如果小于10小时
                df.loc[:, '时间差'].at[i] = f'{standing[8]}小时'
            else:  # 如果大于10小时
                df.loc[:, '时间差'].at[i] = f'{standing[7]}{standing[8]}小时'
        else:
            df.loc[:, '时间差'].at[i] = f'{standing.days}天'
    return indexs


if __name__ == '__main__':
    adder = 'C:/Users/Hp/Desktop/daliy_report'
    output_excel = 'C:/Users/Hp/Desktop/daliy_result.xlsx'  # 生成excel的地址
    df = get_all_excel(adder)  # 将文件夹中的excel文件合并成一个DataFrame
    del_colunms(df)  # 删除掉不需要的列
    clear_data(df)  # 数据清理
    # df = pd.read_excel('daliy_report.xlsx')
    s = input('请输入需要统计几天的日报:')  # 输入需要统计前几天的记录
    s = int(s)
    df['首次告警时间'] = pd.to_datetime(df['首次告警时间'])  # 将列转换为时间类型
    df['最后告警时间'] = pd.to_datetime(df['最后告警时间'])
    df.insert(3, column='时间差', value='0')  # 插入一个名称为时间差的列,value为字符串0
    if s == 1:
        indexs = calau_data(df)  # 输出前一条的记录
        df.loc[indexs].to_excel(output_excel)  # 输出excel表格
    elif s > 1:
        i = 0
        pd.DataFrame().to_excel(output_excel)  # 创建一个空excel表
        while i < s:
            current_time = time.strftime('%Y-%m-%d', time.localtime())  # 当天的日期
            end_data = pd.Timestamp(current_time) - pd.Timedelta(f'{i} days')  # 输出前一天的日期
            start_data = pd.Timestamp(current_time) - pd.Timedelta(f'{i + 1} days')
            sheet_names = str(start_data.strftime('%Y%m%d'))  # excel表中sheet的名称
            indexs = []
            # 筛选出来符合条件的记录的索引
            for index, start_time, end_time in zip(df.index, df['首次告警时间'], df['最后告警时间']):
                if end_time > start_data and start_time < end_data:
                    indexs.append(index)
            # for start_row, start_time in df['首次告警时间'].items():
            #     for end_row, end_time in df['最后告警时间'].items():
            #         if end_time > start_data and start_time < end_data and start_row == end_row:
            #             indexs.append(start_row)
            i += 1
            if len(indexs) == 0:
                continue
            else:
                for n in indexs:  # 遍历索引,计算出来每行的记录的中断持续时间,赋值给时间差那一列
                    standing = end_data - df.at[n, '首次告警时间']  # 计算出来中断持续时间
                    if standing.days == 0:  # 如果中断持续时间小于1天
                        standing = str(standing)  # 将时间类型转成字符串
                        if standing[7] == '0':  # 如果小于10小时
                            df.at[n, '时间差'] = f'{standing[8]}小时'
                        else:  # 如果大于10小时
                            df.at[n, '时间差'] = f'{standing[7]}{standing[8]}小时'
                    else:  # 如果大于1天,获取中断持续时间中的days属性
                        df.at[n, '时间差'] = f'{standing.days}天'
                        print(df.at[n, '时间差'])
                        # print(df.loc[3])   #加上这行代码,结果就不一样了,需要各位解惑
                with pd.ExcelWriter(output_excel, mode='a') as w:  # 将刷选出来的数据写入前面创建的空excel sheet为日期
                    df.loc[indexs].to_excel(w, sheet_name=sheet_names)
                    print(df.loc[3])
    else:
        print("统计日期输入错误")
    print('执行完成')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值