工业工程

工业工程

首页
专业认知
课程体系
方法与工具
软件技能
就业发展
考研深造
院校学科
行业洞察
文章
关于
登录 →
工业工程

工业工程

首页 专业认知 课程体系 方法与工具 软件技能 就业发展 考研深造 院校学科 行业洞察 文章 关于
登录
  1. 首页
  2. 软件技能
  3. 用 Python 做 IE 数据分析:从工时数据到线平衡计算

用 Python 做 IE 数据分析:从工时数据到线平衡计算

0
  • 软件技能
  • 发布于 2025-07-22
  • 14 次阅读
伴读书童
伴读书童
目录
当前文章没有目录

Python 对工业工程的价值,不在于"会编程"这个标签,而在于它能把 IE 每天重复做的分析工作变成可复用、可批量、可追溯的模型。

这篇文章不讲语法基础,直接给三个 IE 高频场景的完整代码:工时数据处理、线平衡计算、仿真建模。

一、环境准备

# 核心库
import pandas as pd        # 数据处理
import numpy as np         # 数值计算
from scipy import stats    # 统计检验
import matplotlib.pyplot as plt   # 可视化

# 优化与仿真(按需安装)
# pip install pulp         # 线性规划
# pip install simpy        # 离散事件仿真
# pip install ortools      # 运筹优化

安装方式建议用 Anaconda 或 pip install pandas numpy scipy matplotlib。

二、场景一:工时数据处理与标准工时计算

2.1 问题

某工位秒表测时,观测了 15 个周期,需要:剔除异常值 → 计算正常时间 → 加宽放 → 得到标准工时。

2.2 代码

import numpy as np
import pandas as pd

def calc_standard_time(observations, rating=1.0, allowance=0.15, verbose=True):
    """标准工时计算:剔除异常值 + 评比 + 宽放"""
    obs = np.array(observations, dtype=float)

    # 1. 三倍标准差法剔除异常值
    while True:
        mean = obs.mean()
        std = obs.std(ddof=1)
        lower, upper = mean - 3 * std, mean + 3 * std
        mask = (obs >= lower) & (obs <= upper)
        if mask.all():
            break
        removed = obs[~mask]
        if verbose:
            print(f"剔除异常值: {removed.round(2).tolist()}")
        obs = obs[mask]

    observed_time = obs.mean()
    normal_time = observed_time * rating
    standard_time = normal_time * (1 + allowance)

    if verbose:
        print(f"有效观测次数: {len(obs)}")
        print(f"观测平均时间: {observed_time:.2f} 秒")
        print(f"评比系数:     {rating}")
        print(f"正常时间:     {normal_time:.2f} 秒")
        print(f"宽放率:       {allowance:.1%}")
        print(f"标准时间:     {standard_time:.2f} 秒")
        print(f"标准差:       {obs.std(ddof=1):.3f}  变异系数: {obs.std(ddof=1)/observed_time:.2%}")

    return standard_time

# 示例:15 次观测,含一个异常值
data = [42.1, 43.5, 41.8, 42.6, 42.9, 43.1, 41.9, 42.4,
        42.7, 68.2, 43.0, 42.3, 41.7, 42.8, 42.5]
st = calc_standard_time(data, rating=1.10, allowance=0.18)

输出解读:

  • 68.2 秒会被自动识别并剔除
  • 变异系数(CV)反映作业稳定性,一般手工装配作业 CV < 10% 说明较稳定

2.3 批量处理多个工位

# 从 Excel 读取多工位测时数据
df = pd.read_excel("工时观测.xlsx")
# 假设格式:工位 | 观测序列(多列)

results = []
for _, row in df.iterrows():
    obs = row.drop("工位").dropna().astype(float).tolist()
    st = calc_standard_time(obs, rating=1.05, allowance=0.15, verbose=False)
    results.append({"工位": row["工位"], "标准工时": round(st, 2)})

result_df = pd.DataFrame(results)
print(result_df)

三、场景二:生产线平衡计算

3.1 问题

给定各工位的标准工时与客户需求节拍,计算:

  • 平衡率与失衡率
  • 理论最少工位数
  • 每日产能
  • 瓶颈工位

3.2 代码

import pandas as pd
import numpy as np

def line_balance(task_times, takt_time=None, available_time=27600, demand=None):
    """产线平衡分析
    task_times: 各工位作业时间列表(秒)
    takt_time: 节拍(秒),与 demand 二选一
    available_time: 每日有效工作时间(秒),默认 460 分钟
    demand: 日需求数量
    """
    tt = np.array(task_times, dtype=float)

    if takt_time is None:
        if demand is None:
            raise ValueError("需提供 takt_time 或 demand")
        takt_time = available_time / demand

    total_time = tt.sum()
    bottleneck = tt.max()
    bottleneck_idx = int(tt.argmax()) + 1
    n_stations = len(tt)

    balance_rate = total_time / (bottleneck * n_stations)
    idle_rate = 1 - balance_rate

    # 理论最少工位数(向上取整)
    min_stations = int(np.ceil(total_time / takt_time))

    # 日产能(受瓶颈限制)
    capacity = int(available_time / bottleneck)

    # 各工位与节拍的差
    diff = tt - takt_time

    return {
        "节拍(秒)": round(takt_time, 2),
        "工位数": n_stations,
        "总作业时间(秒)": round(total_time, 2),
        "瓶颈工位": bottleneck_idx,
        "瓶颈时间(秒)": round(bottleneck, 2),
        "平衡率": f"{balance_rate:.1%}",
        "失衡率": f"{idle_rate:.1%}",
        "理论最少工位数": min_stations,
        "日产能(件)": capacity,
        "超节拍工位": [i + 1 for i, d in enumerate(diff) if d > 0],
        "各工位与节拍差": [round(d, 2) for d in diff],
    }

# 示例
task_times = [32, 41, 28, 25, 39]
res = line_balance(task_times, demand=800, available_time=27600)
for k, v in res.items():
    print(f"{k}: {v}")

3.3 改善方案模拟

def simulate_improvement(task_times, improvements, demand=800, available_time=27600):
    """模拟改善后的平衡效果
    improvements: {工位索引(0起): 改善后的时间}
    """
    tt = np.array(task_times, dtype=float).copy()
    for idx, new_time in improvements.items():
        tt[idx] = new_time
    return line_balance(tt.tolist(), demand=demand, available_time=available_time)

# 假设:W2 通过布局改善降至 30.7,W5 通过电动工具降至 35,
# 并把 1.5 秒作业从 W5 转到 W4
before = line_balance([32, 41, 28, 25, 39], demand=800)
after = line_balance([32, 30.7, 34, 26.5, 33.5], demand=800)

print("\n改善前:", before["平衡率"], "日产能", before["日产能(件)"])
print("改善后:", after["平衡率"], "日产能", after["日产能(件)"])

3.4 用启发式算法做要素分配

当作业要素很多时,人工分配很费劲,可用**最长作业时间优先(LPT)**启发式:

def assign_stations(elements, takt_time):
    """LPT 启发式工位分配
    elements: [(要素名, 时间, 前置要素列表)]
    返回:各工位包含的要素
    """
    # 按时间降序排列
    sorted_elem = sorted(elements, key=lambda x: -x[1])
    stations = [[]]

    for name, time_val, preds in sorted_elem:
        placed = False
        for st in stations:
            station_time = sum(e[1] for e in st)
            assigned_names = [e[0] for e in st]
            # 检查前置约束 & 容量约束
            if all(p in assigned_names for p in preds) and station_time + time_val <= takt_time:
                st.append((name, time_val, preds))
                placed = True
                break
        if not placed:
            stations.append([(name, time_val, preds)])

    return stations

# 示例
elements = [
    ("A1 取外壳", 4.2, []),
    ("A2 贴标签", 5.8, ["A1 取外壳"]),
    ("A3 装主板", 8.5, ["A1 取外壳"]),
    ("A4 锁螺丝", 9.3, ["A3 装主板"]),
    ("A5 通电测试", 6.1, ["A4 锁螺丝"]),
    ("A6 外观检查", 1.5, ["A5 通电测试"]),
]
stations = assign_stations(elements, takt_time=20)
for i, st in enumerate(stations, 1):
    t = sum(e[1] for e in st)
    print(f"工位{i} (负荷 {t:.1f}s): {[e[0] for e in st]}")

四、场景三:离散事件仿真

用 SimPy 建立一个简单的单工序系统,模拟排队与利用率。

import simpy
import random
import statistics

class ProductionLine:
    def __init__(self, env, num_machines, process_time_mean, process_time_std):
        self.env = env
        self.machines = simpy.Resource(env, num_machines)
        self.pt_mean = process_time_mean
        self.pt_std = process_time_std
        self.wait_times = []
        self.throughput = 0

    def process(self, item):
        """单个工件的加工流程"""
        arrive = self.env.now
        with self.machines.request() as req:
            yield req
            self.wait_times.append(self.env.now - arrive)
            pt = max(0.1, random.gauss(self.pt_mean, self.pt_std))
            yield self.env.timeout(pt)
            self.throughput += 1

def source(env, line, arrival_interval, num_items):
    """工件发生器"""
    for i in range(num_items):
        env.process(line.process(f"Item-{i}"))
        yield env.timeout(random.expovariate(1.0 / arrival_interval))

def run_simulation(num_machines=3, pt_mean=10, pt_std=2,
                   arrival_interval=4, num_items=500, sim_time=2000):
    random.seed(42)
    env = simpy.Environment()
    line = ProductionLine(env, num_machines, pt_mean, pt_std)
    env.process(source(env, line, arrival_interval, num_items))
    env.run(until=sim_time)

    utilization = (pt_mean * line.throughput) / (num_machines * sim_time)
    return {
        "吞吐量": line.throughput,
        "平均等待时间": round(statistics.mean(line.wait_times), 2),
        "最大等待时间": round(max(line.wait_times), 2),
        "设备利用率": f"{utilization:.1%}",
    }

# 对比不同设备数量的效果
for n in [2, 3, 4, 5]:
    r = run_simulation(num_machines=n)
    print(f"设备数={n}: 吞吐={r['吞吐量']}, 平均等待={r['平均等待时间']}s, "
          f"利用率={r['设备利用率']}")

这段代码的 IE 价值:在设备投资决策前,用仿真回答"再加一台设备能提升多少产出、等待时间能降多少",比拍脑袋决策可靠得多。

五、场景四:运筹优化(排产)

用 PuLP 求解一个简单的生产计划问题。

import pulp

def production_planning(products, resources, profit, usage, capacity):
    """产品组合优化
    products: 产品列表
    resources: 资源(工序)列表
    profit: {产品: 单位利润}
    usage: {产品: {资源: 单位消耗}}
    capacity: {资源: 可用能力}
    """
    prob = pulp.LpProblem("ProductMix", pulp.LpMaximize)
    x = {p: pulp.LpVariable(f"x_{p}", lowBound=0, cat="Integer") for p in products}

    # 目标函数:最大化利润
    prob += pulp.lpSum(profit[p] * x[p] for p in products)

    # 约束:资源能力限制
    for r in resources:
        prob += pulp.lpSum(usage[p][r] * x[p] for p in products) <= capacity[r]

    prob.solve(pulp.PULP_CBC_CMD(msg=False))

    return {p: int(x[p].value()) for p in products}, pulp.value(prob.objective)

# 示例
products = ["A", "B", "C"]
resources = ["机加", "装配", "检验"]
profit = {"A": 120, "B": 180, "C": 150}
usage = {
    "A": {"机加": 2, "装配": 3, "检验": 1},
    "B": {"机加": 4, "装配": 3, "检验": 2},
    "C": {"机加": 3, "装配": 4, "检验": 1},
}
capacity = {"机加": 800, "装配": 900, "检验": 400}

plan, total = production_planning(products, resources, profit, usage, capacity)
print("最优生产计划:", plan)
print("最大利润:", round(total, 2))

六、可视化:让数据说话

import matplotlib.pyplot as plt
import numpy as np

def plot_yamazumi(task_times, takt_time, labels=None):
    """山积图:工位负荷可视化"""
    n = len(task_times)
    if labels is None:
        labels = [f"W{i+1}" for i in range(n)]

    fig, ax = plt.subplots(figsize=(10, 5))
    colors = ["#d62728" if t > takt_time else "#2ca02c" for t in task_times]
    bars = ax.bar(labels, task_times, color=colors, alpha=0.85)

    ax.axhline(takt_time, color="black", linestyle="--", linewidth=1.5,
               label=f"节拍 {takt_time}s")

    balance = sum(task_times) / (max(task_times) * n)
    ax.set_title(f"产线平衡山积图(平衡率 {balance:.1%})", fontsize=13)
    ax.set_ylabel("作业时间 (秒)")
    ax.legend()

    for bar, t in zip(bars, task_times):
        ax.text(bar.get_x() + bar.get_width()/2, t + 0.5,
                f"{t}", ha="center", fontsize=10)

    plt.tight_layout()
    plt.show()

plot_yamazumi([32, 41, 28, 25, 39], takt_time=34.5)

中文显示问题:Matplotlib 默认不支持中文,需设置字体:

plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False

七、学习路径建议

阶段 内容 产出
第 1 个月 Python 基础 + pandas 能用 pandas 替代 Excel 做数据处理
第 2 个月 numpy + scipy.stats 能独立做假设检验与分布拟合
第 3 个月 matplotlib 可视化 能做出专业级图表
第 4–5 个月 仿真(simpy)与优化(PuLP) 能建模求解实际问题
第 6 个月 综合项目 一个完整的 IE 数据分析项目

八、务实提醒

  1. 不要为了学 Python 而学:先用它解决一个真实问题(课程作业、竞赛、实习项目)
  2. 能跑通比写得优雅重要:IE 场景下,脚本是工具不是产品
  3. 结果要能解释:给管理层汇报时,代码的复杂度不重要,结论的可解释性才重要
  4. Excel 仍是主战场:Python 处理完的数据,很多时候还是要输出到 Excel 给同事看

延伸阅读

  • 《工业工程必备软件地图:从 Excel 到 FlexSim,每个阶段该学什么》
  • 《生产线平衡:从节拍、瓶颈到平衡率改善的完整方法》

相关阅读

  • 工业工程必备软件地图:从 Excel 到 FlexSim,每个阶段该学什么:按学习阶段给出 IE 的软件全景图:Excel、统计分析、仿真建模、CAD、企业系统,并给出…
  • Python 与 VBA:工业工程自动化的两条路径怎么选:每周花 4 小时做同一份报表,一年就是 200 小时。本文系统对比两条自动化路径:VBA(E…
  • SQL 工业工程数据分析实战:从 MES 取数到指标看板:IE 日常有 60% 的时间花在等数据上。本文从真实取数场景出发,讲透 SQL 核心语法(S…
  • 工业工程师的 Excel 实战手册:从工时分析、过程能力到线平衡的 30 个技法:面向 IE 场景的 Excel 实操手册:连续测时数据差分还原、IQR 与 3σ 异常值剔除…
  • 工业工程数据与指标看板:从指标定义、采集口径到可视化落地的完整手册:从指标定义卡 12 要素讲到看板落地:OEE 三种分母口径对照(负荷 75.45% / 计划…
相关文章
Visio 与流程图实战:价值流图、工序流程图与业务建模

Visio 与流程图实战:价值流图、工序流程图与业务建模

一张画得对的价值流图,能让改善讨论从「我觉得」变成「数据显示」。本文讲透:工具选型(Visio/draw.io/Mermaid 等十款对比)、流程图四层体系(工序流程/业务泳道/价值流/BPMN)、工序分析五种符号与流程程序图、VSM 完整绘制法(现状图七步、数据框填法、时间线与增值比、未来图设计六问、定拍工序)、泳道图画法、Visio 与 draw.io 高效操作技巧、让图能沟通的九原则,以及一套装配线 VSM 落地案例。

Python 与 VBA:工业工程自动化的两条路径怎么选

Python 与 VBA:工业工程自动化的两条路径怎么选

每周花 4 小时做同一份报表,一年就是 200 小时。本文系统对比两条自动化路径:VBA(Excel 原生、零部署、适合操作 Excel 本身)与 Python(生态强大、适合数据处理与跨系统),给出明确选型决策树;讲透 VBA 核心能力(宏录制、Range、数组优化、事件、代码片段)与 Python 数据处理栈(pandas、openpyxl、数据清洗七步),含五个可复制案例(多文件合并、BOM 比对、工时清洗、批量重命名、自动发邮件报表)和九个新手坑。

MES 系统完全指南:从原理、选型到落地实施

MES 系统完全指南:从原理、选型到落地实施

MES 是工厂数字化投入最大、失败率也最高的系统之一。本文讲透:MES 到底解决什么问题(ERP 和 SCADA 为何解决不了)、ISA-95 五层架构与 MES 定位、十一大核心功能模块、与 ERP/QMS/WMS/SCADA 的边界与集成接口、三种数据采集方式的取舍与老设备改造方案、选型评估六维度、实施五阶段与分批上线策略,以及八个常见陷阱——包括为什么「先上 MES 再理流程」必然失败。

Power BI 工业工程看板实战:从数据到管理驾驶舱

Power BI 工业工程看板实战:从数据到管理驾驶舱

每天早会 25 分钟花在对数字上,根源是没有口径统一、自动刷新的数据源。本文讲透 Power BI 完整链路:何时该用何时不该、Power Query 数据清洗十类操作与逆透视、星型模型与表关系设计、DAX 核心(计算列 vs 度量值、筛选上下文、CALCULATE、迭代函数、时间智能)、十五个生产管理度量值代码、图表选择与避坑、网关刷新与行级安全,以及看板设计七原则和一套 OEE 管理驾驶舱落地案例。

SQL 工业工程数据分析实战:从 MES 取数到指标看板

SQL 工业工程数据分析实战:从 MES 取数到指标看板

IE 日常有 60% 的时间花在等数据上。本文从真实取数场景出发,讲透 SQL 核心语法(SELECT/WHERE/GROUP BY/JOIN/子查询/CTE/窗口函数/日期处理)、MES 与 ERP 的典型表结构与 ER 关系、如何快速摸清陌生数据库、十二个高频实战查询模板(OEE、工单周期、瓶颈识别、不良帕累托、停机归因、WIP 追踪、挣值工时、正反向追溯、同比环比、换型矩阵、技能矩阵、呆滞库存),以及六大陷阱(一对多重复计数、NULL 静默丢数、日期边界、时区班次、粒度错误、生产库性能)。

AutoCAD 工厂布局实战:从平面图到可落地的设施规划

AutoCAD 工厂布局实战:从平面图到可落地的设施规划

一张合格的车间布局图要能直接拿去施工、报消防、做产能核算、给仿真建模。本文系统讲解 IE 用 AutoCAD 做设施规划的完整链路:软件选型、国标制图规范、高频命令速查、设备图块库与动态块建设、SLP 五步法、厂区级与车间级布局要点、消防与安全间距、人机工程尺寸应用,以及从 CAD 到仿真的数字化交付。

目录
当前文章没有目录
Copyright © 2002 CUMT All Rights Reserved. Powered by 中国矿业大学工业工程系.
粤ICP备2024349181号-3