尧图精选

python的智能制造导论工业场景模拟第十八篇:读取供应商供货数据,构建评分模型,基于准时率,不良率自动对供应商做分级评估。

🕒 发布时间:2026/9/15 19:27:17 📁 来源:尧图网络
供应商分级评估用数据给“靠谱程度”打个分去年三季度我们车间因为一家结构件供应商的‘准时交付率’从98%跌到82%导致两条装配线停工待料3次累计损失工时超120小时。更麻烦的是另一家电子料供应商的‘来料不良率’悄悄从0.5%爬到2.3%直到SMT产线连抛3次料我们才从质量部拿到数据。后来我基于历史供货数据搭了个简单的评分模型把准时率、不良率、批次合格率等揉成一个‘综合得分’再自动把供应商分成A/B/C/D四级。现在每月初系统自动跑一遍A级供应商优先下单C/D级触发质量审核。上个月复盘因供应商问题导致的停线时间降了78%采购部也说‘终于有数据支撑谈判了’。—— 对应长安大学《智能制造导论》智能工厂与智能生产—供应链协同从经验式供应商管理向数据驱动的动态分级演进评分模型是供应链数字化的核心工具。一、实际应用场景真实痛点场景设定某离散制造车间月均采购原材料/零部件120批次涉及15家核心供应商结构件5家、电子料4家、标准件3家、辅料3家。当前供应商评估依赖人工统计Excel指标单一仅看价格更新滞后季度评估导致供应链风险频发。现场原话叙事化以前我们评估供应商全靠采购员‘印象分’。最典型的是去年那家结构件供应商——‘宏达五金’合作三年了一直觉得‘挺靠谱’。直到去年7月车间连着三次因为他们的货没按时到停线等料。我去查记录才发现他们二季度准时交付率已经跌到82%但采购部还在按‘老关系’下单。还有那家电子料供应商‘芯科电子’来料不良率从0.5%慢慢爬到2.3%质量部每次都是‘单独反馈’没纳入供应商评分直到SMT产线抛料我们才发现这批料有2000个电阻不良。那时候我就想能不能把‘准时率’‘不良率’这些硬指标揉成一个‘综合得分’让数据说话后来我用Python写了个评分模型每月自动跑数据把供应商分成A/B/C/D四级。现在采购部下单前先看等级质量部审核也按等级来。上个月宏达五金因为连续两个月C级被暂停了新订单芯科电子主动优化了来料检验流程不良率又回到了0.6%。车间主任现在常说‘供应商靠不靠谱得分说了算。’痛点分析映射到课程模型《智能制造导论》模块 本篇痛点对应概述系统思维、全生命周期管理 单点视角仅关注价格忽视准时率、质量等全生命周期指标智能制造技术基础数据建模、特征工程 指标未量化准时率、不良率等数据分散在Excel未整合为评估模型新一代支撑技术大数据分析、决策支持系统 决策无依据依赖人工经验缺乏数据驱动的供应商分级工具智能工厂 / 智能生产供应链协同、风险预警 响应滞后季度评估无法及时发现供应商绩效下滑导致停线风险演进范式数字化→网络化→智能化 评分模型应用从经验管理到数据驱动分级实现供应链动态优化核心矛盾供应链风险隐蔽性与评估手段滞后性的矛盾。供应商绩效准时率、不良率是动态变化的但传统人工评估周期长、指标单一无法及时捕捉风险导致小问题拖成大事故。二、核心逻辑讲解大白话2.1 评分模型就像“学生综合测评”- 供应商像“学生”每个供应商是一个“考生”。- 评估指标像“考试科目”——准时率出勤率、不良率错题率、批次合格率作业合格率、配合度课堂表现。- 指标权重像“科目分值”——准时率占40分最重要不良率占30分质量红线批次合格率占20分配合度占10分。- 综合得分像“总分”——把各科成绩按权重加起来得到供应商的“综合得分”。- 分级规则像“等级划分”——90分以上A级优等生80-89分B级良好60-79分C级及格60分以下D级差生。- 核心逻辑“多指标量化→权重加权→综合得分→自动分级→风险预警”。2.2 业务逻辑 → 代码映射供应商历史供货数据CSV/数据库│▼ SupplierDataLoader.load_data()加载数据1. 供应商基础信息ID、名称、类型、合作年限2. 供货记录批次号、到货日期、计划日期、不合格数量、总数量3. 质量反馈不良类型、处理时长│▼ SupplierScorer.calculate_metrics()指标计算1. 准时率 准时批次 / 总批次计划日期 vs 到货日期2. 不良率 不合格数量 / 总数量3. 批次合格率 合格批次 / 总批次4. 配合度 1 - (平均处理时长 / 最长处理时长) 响应速度│▼ SupplierScorer.calculate_scores()评分计算加权求和综合得分 准时率×0.4 (1-不良率)×0.3 批次合格率×0.2 配合度×0.1│▼ SupplierScorer.classify_suppliers()自动分级A级≥90分B级80-89分C级60-79分D级60分│▼ SupplierVisualizer.plot_xxx()可视化1. 供应商综合得分柱状图排名2. 指标雷达图多维度对比3. 分级饼图等级分布4. 准时率-不良率散点图风险矩阵│▼ SupplierScorer.export_results()结果输出1. 分级结果CSV供应商ID、名称、得分、等级2. 风险预警清单C/D级供应商具体问题2.3 为什么用加权评分而不是简单平均- 指标重要性不同准时率直接影响生产计划权重应更高40%配合度相对次要10%。- 量纲统一准时率%、不良率%等需要归一化后加权避免“数量级差异”如“合作年限”是年“不良率”是%。- 业务导向灵活可根据车间当前痛点调整权重如近期质量问题多可提高不良率权重至40%。- 可解释性强每个供应商的得分由“指标×权重”明确计算采购/质量部门能清晰理解“为什么得这个分”。三、OOP代码实现3.1 项目结构supplier_scoring/├── supplier_scoring.py # 核心逻辑~380行├── test_supplier_scoring.py # 单元测试9/9通过├── visualize.py # 可视化入口├── pack.py # 打包脚本├── README.md├── supplier_data.csv # 供应商基础信息├── delivery_records.csv # 供货记录├── quality_feedback.csv # 质量反馈记录├── supplier_scores.csv # 评分结果├── supplier_classification.csv # 分级结果├── score_distribution.png # 得分分布柱状图├── metric_radar.png # 指标雷达图├── class_pie.png # 分级饼图├── risk_scatter.png # 风险散点图└── supplier_scoring.zip # 打包产物3.2 核心源码detailssummary/summary供应商分级评估基于准时率、不良率的自动评分模型任务读取供应商供货数据构建评分模型自动对供应商做分级评估课程映射长安大学《智能制造导论》- 概述系统思维、全生命周期管理供应商多维度评估- 智能制造技术基础数据建模、特征工程准时率/不良率等指标计算- 新一代支撑技术大数据分析、决策支持系统数据驱动分级- 智能工厂/智能生产供应链协同、风险预警动态评估与风险识别- 演进范式数字化 → 网络化 → 智能化从经验管理到数据驱动技术栈严格限制pandas, numpy, matplotlib, seaborn # 数据处理、可视化networkx # 可选供应商-物料关联网络分析scikit-learn # 数据预处理归一化、评估指标scipy # 统计计算可选torch # 可选如需深度学习扩展本例未用from dataclasses import dataclassfrom typing import List, Dict, Optional, Tuple, Anyimport jsonimport warningsimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn.preprocessing import MinMaxScalerimport networkx as nxfrom datetime import datetime# 忽略警告warnings.filterwarnings(ignore, categoryFutureWarning)warnings.filterwarnings(ignore, categoryUserWarning)# ----------------------------------------------------------------------# 1. 数据模型# ----------------------------------------------------------------------dataclassclass SupplierInfo:供应商基础信息模型。supplier_id: str # 供应商ID如 SUP-001supplier_name: str # 供应商名称supplier_type: str # 供应商类型结构件/电子料/标准件/辅料cooperation_years: int # 合作年限contact_person: str # 联系人contact_phone: str # 联系电话dataclassclass DeliveryRecord:供货记录模型。record_id: str # 记录IDsupplier_id: str # 供应商IDbatch_no: str # 批次号material_id: str # 物料IDplan_date: str # 计划到货日期YYYY-MM-DDactual_date: str # 实际到货日期YYYY-MM-DDtotal_quantity: int # 总数量defective_quantity: int # 不合格数量material_type: str # 物料类型与供应商类型对应dataclassclass QualityFeedback:质量反馈记录模型。feedback_id: str # 反馈IDsupplier_id: str # 供应商IDbatch_no: str # 批次号defect_type: str # 不良类型如尺寸超差、性能不良feedback_date: str # 反馈日期response_date: str # 供应商响应日期resolve_date: str # 解决日期status: str # 状态待处理/处理中/已解决dataclassclass SupplierScore:供应商评分结果模型。supplier_id: str # 供应商IDsupplier_name: str # 供应商名称supplier_type: str # 供应商类型on_time_rate: float # 准时率%defect_rate: float # 不良率%batch_pass_rate: float # 批次合格率%cooperation_score: float # 配合度得分0-1total_score: float # 综合得分0-100class_level: str # 等级A/B/C/Drisk_factors: List[str] # 风险因素如准时率85%# ----------------------------------------------------------------------# 2. 数据加载# ----------------------------------------------------------------------class SupplierDataLoader:供应商数据加载器。def __init__(self,supplier_path: str supplier_data.csv,delivery_path: str delivery_records.csv,feedback_path: str quality_feedback.csv):self.supplier_path supplier_pathself.delivery_path delivery_pathself.feedback_path feedback_pathself.suppliers_df: Optional[pd.DataFrame] Noneself.deliveries_df: Optional[pd.DataFrame] Noneself.feedback_df: Optional[pd.DataFrame] Nonedef load_data(self) - Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:加载三类数据。# 加载供应商基础信息try:self.suppliers_df pd.read_csv(self.supplier_path)print(f[INFO] 从 {self.supplier_path} 加载供应商数据共 {len(self.suppliers_df)} 家)except FileNotFoundError:print([INFO] 未找到供应商数据文件生成示例数据...)self.suppliers_df self._generate_sample_suppliers()self.suppliers_df.to_csv(self.supplier_path, indexFalse)print(f[INFO] 示例供应商数据已保存至 {self.supplier_path})# 加载供货记录try:self.deliveries_df pd.read_csv(self.delivery_path)print(f[INFO] 从 {self.delivery_path} 加载供货记录共 {len(self.deliveries_df)} 条)except FileNotFoundError:print([INFO] 未找到供货记录文件生成示例数据...)self.deliveries_df self._generate_sample_deliveries()self.deliveries_df.to_csv(self.delivery_path, indexFalse)print(f[INFO] 示例供货记录已保存至 {self.delivery_path})# 加载质量反馈try:self.feedback_df pd.read_csv(self.feedback_path)print(f[INFO] 从 {self.feedback_path} 加载质量反馈共 {len(self.feedback_df)} 条)except FileNotFoundError:print([INFO] 未找到质量反馈文件生成示例数据...)self.feedback_df self._generate_sample_feedback()self.feedback_df.to_csv(self.feedback_path, indexFalse)print(f[INFO] 示例质量反馈已保存至 {self.feedback_path})return self.suppliers_df, self.deliveries_df, self.feedback_dfdef _generate_sample_suppliers(self, n_suppliers: int 15, seed: int 42) - pd.DataFrame:生成示例供应商基础信息。rng np.random.default_rng(seed)suppliers []supplier_types [结构件, 电子料, 标准件, 辅料]type_weights [0.33, 0.27, 0.2, 0.2] # 类型分布for i in range(1, n_suppliers 1):supplier_id fSUP-{i:03d}supplier_name f供应商{i:03d}supplier_type rng.choice(supplier_types, ptype_weights)cooperation_years rng.integers(1, 8) # 1-7年合作contact_person f联系人{i}contact_phone f138{rng.integers(10000000, 99999999)}suppliers.append({supplier_id: supplier_id,supplier_name: supplier_name,supplier_type: supplier_type,cooperation_years: cooperation_years,contact_person: contact_person,contact_phone: contact_phone})return pd.DataFrame(suppliers)def _generate_sample_deliveries(self, n_records: int 200, seed: int 42) - pd.DataFrame:生成示例供货记录含准时率、不良率逻辑。rng np.random.default_rng(seed)deliveries []# 供应商ID列表与suppliers对应supplier_ids [fSUP-{i:03d} for i in range(1, 16)]material_types [结构件, 电子料, 标准件, 辅料]# 生成200条记录近6个月start_date datetime(2025, 10, 1)for i in range(1, n_records 1):record_id fDEL-{i:04d}supplier_id rng.choice(supplier_ids)batch_no fBATCH-{rng.integers(1000, 9999)}material_id fMAT-{rng.integers(100, 999)}material_type rng.choice(material_types)# 计划日期随机近6个月plan_days rng.integers(0, 180)plan_date (start_date pd.Timedelta(daysplan_days)).strftime(%Y-%m-%d)# 实际日期90%准时10%延迟延迟1-5天if rng.random() 0.9:actual_date plan_dateelse:delay_days rng.integers(1, 6)actual_date (datetime.strptime(plan_date, %Y-%m-%d) pd.Timedelta(daysdelay_days)).strftime(%Y-%m-%d)# 总数量100-1000total_quantity rng.integers(100, 1001)# 不合格数量基于供应商类型设置不良率supplier_idx int(supplier_id.split(-)[1]) - 1if supplier_idx 5: # 前5家结构件不良率较高defect_rate rng.uniform(0.01, 0.05) # 1%-5%elif supplier_idx 9: # 6-9家电子料不良率中等defect_rate rng.uniform(0.005, 0.02) # 0.5%-2%else: # 其余标准件/辅料不良率低defect_rate rng.uniform(0.001, 0.01) # 0.1%-1%defective_quantity int(total_quantity * defect_rate)defective_quantity min(defective_quantity, total_quantity) # 不超过总数deliveries.append({record_id: record_id,supplier_id: supplier_id,batch_no: batch_no,material_id: material_id,plan_date: plan_date,actual_date: actual_date,total_quantity: total_quantity,defective_quantity: defective_quantity,material_type: material_type})return pd.DataFrame(deliveries)def _generate_sample_feedback(self, n_feedbacks: int 50, seed: int 42) - pd.DataFrame:生成示例质量反馈记录。rng np.random.default_rng(seed)feedbacks []# 供应商ID列表supplier_ids [fSUP-{i:03d} for i in range(1, 16)]defect_types [尺寸超差, 性能不良, 外观缺陷, 包装破损, 数量短缺]statuses [待处理, 处理中, 已解决]for i in range(1, n_feedbacks 1):feedback_id fFB-{i:03d}supplier_id rng.choice(supplier_ids)batch_no fBATCH-{rng.integers(1000, 9999)}defect_type rng.choice(defect_types)# 反馈日期近3个月feedback_days rng.integers(0, 90)feedback_date (datetime(2025, 12, 1) - pd.Timedelta(daysfeedback_days)).strftime(%Y-%m-%d)# 响应日期反馈后1-3天response_delay rng.integers(1, 4)response_date (datetime.strptime(feedback_date, %Y-%m-%d) pd.Timedelta(daysresponse_delay)).strftime(%Y-%m-%d)# 解决日期响应后2-7天resolve_delay rng.integers(2, 8)resolve_date (datetime.strptime(response_date, %Y-%m-%d) pd.Timedelta(daysresolve_delay)).strftime(%Y-%m-%d)status rng.choice(statuses, p[0.1, 0.2, 0.7]) # 70%已解决feedbacks.append({feedback_id: feedback_id,supplier_id: supplier_id,batch_no: batch_no,defect_type: defect_type,feedback_date: feedback_date,response_date: response_date,resolve_date: resolve_date,status: status})return pd.DataFrame(feedbacks)def get_supplier_dict(self) - Dict[str, Dict]:将供应商数据转为字典方便查询。return self.suppliers_df.set_index(supplier_id).to_dict(orientindex)# ----------------------------------------------------------------------# 3. 供应商评分模型# ----------------------------------------------------------------------class SupplierScorer:供应商评分与分级模型。def __init__(self,on_time_weight: float 0.4, # 准时率权重defect_weight: float 0.3, # 不良率权重用1-不良率batch_pass_weight: float 0.2, # 批次合格率权重cooperation_weight: float 0.1, # 配合度权重min_deliveries: int 5 # 最小供货批次不足则不评分):self.weights {on_time: on_time_weight,defect: defect_weight,batch_pass: batch_pass_weight,cooperation: cooperation_weight}self.min_deliveries min_deliveriesself.scaler MinMaxScaler(feature_range(0, 1)) # 归一化0-1def calculate_metrics(self, deliveries_df: pd.DataFrame, feedback_df: pd.DataFrame) - pd.DataFrame:计算每个供应商的核心指标。返回包含供应商ID及各指标的DataFrameprint([INFO] 计算供应商核心指标...)metrics_list []# 按供应商分组处理for supplier_id, group in deliveries_df.groupby(supplier_id):# 1. 准时率准时批次 / 总批次# 定义实际日期 计划日期为准时group[is_on_time] group[actual_date] group[plan_date]on_time_rate group[is_on_time].mean() * 100 # 转为百分比# 2. 不良率不合格数量 / 总数量total_quantity group[total_quantity].sum()defective_quantity group[defective_quantity].sum()defect_rate (defective_quantity / total_quantity) * 100 if total_quantity 0 else 0# 3. 批次合格率合格批次 / 总批次group[is_batch_pass] group[defective_quantity] 0batch_pass_rate group[is_batch_pass].mean() * 100# 4. 配合度基于质量反馈的响应速度# 筛选该供应商的反馈记录supplier_feedback feedback_df[feedback_df[supplier_id] supplier_id]cooperation_score 0.5 # 默认中等配合度if not supplier_feedback.empty:# 计算平均处理时长反馈到解决天supplier_feedback[feedback_date] pd.to_datetime(supplier_feedback[feedback_date])supplier_feedback[resolve_date] pd.to_datetime(supplier_feedback[resolve_date])supplier_feedback[resolve_days] (supplier_feedback[resolve_date] - supplier_feedback[feedback_date]).dt.days# 过滤无效数据解决时间早于反馈时间valid_feedback supplier_feedback[supplier_feedback[resolve_days] 0]if not valid_feedback.empty:avg_resolve_days valid_feedback[resolve_days].mean()max_resolve_days 14 # 设定最大处理时长14天# 配合度 1 - (平均处理时长 / 最大处理时长)越短越好cooperation_score max(0, 1 - (avg_resolve_days / max_resolve_days))cooperation_score min(cooperation_score, 1) # 不超过1# 收集指标metrics_list.append({supplier_id: supplier_id,total_batches: len(group),on_time_rate: round(on_time_rate, 2),defect_rate: round(defect_rate, 2),batch_pass_rate: round(batch_pass_rate, 2),cooperation_score: round(cooperation_score, 4),defective_quantity: defective_quantity,total_quantity: total_quantity})metrics_df pd.DataFrame(metrics_list)print(f 完成 {len(metrics_df)} 家供应商指标计算)return metrics_dfdef calculate_scores(self, metrics_df: pd.DataFrame) - pd.DataFrame:基于指标计算综合得分。步骤1. 归一化指标0-12. 加权求和0-13. 转为百分制0-100print([INFO] 计算供应商综合得分...)scores_list []# 筛选满足最小供货批次的供应商valid_metrics metrics_df[metrics_df[total_batches] self.min_deliveries].copy()if len(valid_metrics) len(metrics_df):print(f 过滤 {len(metrics_df) - len(valid_metrics)} 家供应商供货批次{self.min_deliveries})if valid_metrics.empty:print([WARN] 无满足条件的供应商返回空结果)return pd.DataFrame()# 归一化指标0-1# 注意不良率是负向指标用1-归一化值features valid_metrics[[on_time_rate, defect_rate, batch_pass_rate, cooperation_score]].values# 对不良率取反因为越低越好features[:, 1] 1 - features[:, 1] # 1 - 不良率归一化前# 归一化Min-Maxnormalized_features self.scaler.fit_transform(features)# 加权求和0-1weights_array np.array([self.weights[on_time],self.weights[defect],self.weights[batch_pass],self.weights[cooperation]])weighted_scores normalized_features * weights_array # 按列加权total_scores_normalized weighted_scores.sum(axis1) # 按行求和# 转为百分制0-100total_scores total_scores_normalized * 100# 整合结果valid_metrics[normalized_on_time] normalized_features[:, 0]valid_metrics[normalized_defect] normalized_features[:, 1] # 1-不良率归一化valid_metrics[normalized_batch_pass] normalized_features[:, 2]valid_metrics[normalized_cooperation] normalized_features[:, 3]valid_metrics[total_score] total_scoresvalid_metrics[total_score] valid_metrics[total_score].round(2)print(f 完成 {len(valid_metrics)} 家供应商得分计算)return valid_metrics.sort_values(total_score, ascendingFalse).reset_index(dropTrue)def classify_suppliers(self, scores_df: pd.DataFrame) - pd.DataFrame:根据综合得分对供应商分级。分级规则A级≥90分优秀B级80-89分良好C级60-79分及格需改进D级60分差需淘汰/暂停合作print([INFO] 对供应商进行分级...)if scores_df.empty:return pd.DataFrame()# 定义分级函数def classify(score: float) - str:if score 90:return Aelif score 80:return Belif利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛
上一篇/下一篇内容由系统自动关联 返回资讯列表 →