import os
import pandas as pd
import warnings
from collections import defaultdict
# 关闭警告
warnings.filterwarnings('ignore')
# 文件路径设置
desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
folder_path = os.path.join(desktop_path, '洛阳')
output_path = os.path.join(desktop_path, '故障分析结果')
os.makedirs(output_path, exist_ok=True)
def smart_column_mapping(df):
"""智能匹配列名并返回映射字典"""
# 创建列名映射字典
col_map = {}
# 可能的列名变体(不区分大小写和空格)
possible_names = {
'fsu': ['厂家', 'fsu厂家', '生产厂家', '厂商'],
'device': ['设备类型', '设备名称', '设备型号', '类型'],
'alarm': ['告警描述', '告警内容', '告警信息', '告警详情']
}
# 遍历实际列名进行匹配
for actual_col in df.columns:
lowered = str(actual_col).strip().lower().replace(' ', '')
# FSU厂家列匹配
if any(kw in lowered for kw in possible_names['fsu']):
col_map['fsu'] = actual_col
# 设备类型列匹配
if any(kw in lowered for kw in possible_names['device']):
col_map['device'] = actual_col
# 告警描述列匹配
if any(kw in lowered for kw in possible_names['alarm']):
col_map['alarm'] = actual_col
return col_map
def process_file(file_path):
# 读取Excel(增加处理合并单元格的功能)
df = pd.read_excel(file_path, header=None) # 先不跳过任何行
# 自动检测标题行(查找包含关键字的行)
header_row = None
for i in range(min(5, len(df))): # 检查前5行
if any('站点' in str(cell) for cell in df.iloc[i]) and \
any('设备类型' in str(cell) for cell in df.iloc[i]):
header_row = i
break
# 重新读取文件,指定标题行
if header_row is not None:
df = pd.read_excel(file_path, header=header_row)
print(f"检测到标题行: {header_row+1}")
else:
print(f"警告: 无法确定标题行,使用默认读取")
df = pd.read_excel(file_path, skiprows=2) # 原始逻辑
# 打印实际列名用于调试
print(f"文件列名: {list(df.columns)}")
# 获取列映射
col_map = smart_column_mapping(df)
print(f"列映射: {col_map}")
if not all(key in col_map for key in ['fsu', 'device', 'alarm']):
missing = [key for key in ['fsu', 'device', 'alarm'] if key not in col_map]
print(f"缺少必要列: {missing}")
return None
# 更灵活的筛选条件
device_mask = df[col_map['device']].astype(str).str.contains('开关电源|电源柜|电源设备')
alarm_mask = df[col_map['alarm']].astype(str).str.contains('交流输入故障|AC输入故障|市电故障')
filtered_df = df[device_mask & alarm_mask]
# 打印匹配结果用于调试
print(f"找到匹配记录: {len(filtered_df)}条")
# 提取必要字段
result_cols = [col_map['fsu'], col_map['device'], col_map['alarm']]
return filtered_df[result_cols] if not filtered_df.empty else None
# 主处理流程
all_results = []
fault_counts = defaultdict(int)
for file in os.listdir(folder_path):
if file.lower().endswith(('.xlsx', '.xls')):
full_path = os.path.join(folder_path, file)
print(f"\n{'='*40}")
print(f"处理文件: {file}")
try:
result = process_file(full_path)
if result is not None:
all_results.append(result)
# 统计厂家故障次数
for manufacturer in result[smart_column_mapping(result)['fsu']]:
fault_counts[manufacturer] += 1
print(f"✅ 成功提取{len(result)}条记录")
except Exception as e:
print(f"处理失败: {str(e)}")
# 结果输出
if all_results:
final_df = pd.concat(all_results)
detail_file = os.path.join(output_path, '故障详情.xlsx')
final_df.to_excel(detail_file, index=False)
print(f"\n导出详情到: {detail_file}")
# 厂家统计
stats_df = pd.DataFrame({
'厂家': list(fault_counts.keys()),
'故障次数': list(fault_counts.values())
}).sort_values('故障次数', ascending=False)
stats_file = os.path.join(output_path, '厂家统计.xlsx')
stats_df.to_excel(stats_file, index=False)
print(f"导出统计到: {stats_file}")
# 打印示例数据
print("\n示例数据:")
print(final_df.head(3))
else:
print("\n⚠️ 所有文件均未找到匹配数据")
print("\n处理完成!")
处理文件: 6.12.xls
检测到标题行: 3
文件列名: ['序号', '地市', '告警编号', '区域', '站点', '机房', '机房类型', '设备', '设备类型', '业务类型', '告警标准编码', 'FSU厂家', '告警量', '告警级别', '告警时间', '告警接收时间', '消除时间', '消除接收时间', '告警时长(分钟)', '告警值', '告警描述', '告警编码', '告警逻辑分类', '告警逻辑子类', '确认人', '确认时间', '确认说明', '告警标准化名称', '告警标题', '屏 蔽类型']
列映射: {'device': '屏蔽类型', 'fsu': 'FSU厂家', 'alarm': '告警描述'}
找到匹配记录: 0条,为什么没找到匹配记录,请解决该问题