在Pandas中通过循环为指定行添加标签列的技术问题
解决Pandas中为故障行前后行添加标签的问题
需求
给DataFrame新增label列:只要某行的failure值为1,就将该行、它的前2行、后1行都打上同一个标签。
你尝试的代码
df_new = pd.DataFrame() for i in range(0, len(df)): if df.iloc[i]['failure'] == 1: n += 1 df_new = df_new.append(df.iloc[i-2:i+2]) df_new = df_new.append({'label': n}, ignore_index=True)
当前错误结果
| var_1 | var_2 | failure | label |
|---|---|---|---|
| 75.0 | 55.0 | 0.0 | NaN |
| 45.0 | 19.0 | 0.0 | NaN |
| 76.0 | 46.0 | 1.0 | NaN |
| 18.0 | 63.0 | 0.0 | NaN |
| NaN | NaN | NaN | 1.0 |
期望正确结果
| var_1 | var_2 | failure | label |
|---|---|---|---|
| 75.0 | 55.0 | 0.0 | 1 |
| 45.0 | 19.0 | 0.0 | 1 |
| 76.0 | 46.0 | 1.0 | 1 |
| 18.0 | 63.0 | 0.0 | 1 |
问题根源
你原来的代码有两个核心问题:
- 用
append循环拼接DataFrame效率低,且单独追加仅含label的行,导致出现全NaN的无效记录; - 没有直接为选中的行赋值标签,而是把行数据和标签分开追加,无法将标签对应到正确的行上。
正确实现方法
方法1:基础循环赋值(易理解)
直接在原DataFrame上操作,定位每个故障行的前后范围并赋值:
import pandas as pd # 初始化label列为空值 df['label'] = pd.NA label_num = 0 # 遍历所有failure=1的行索引 for idx in df[df['failure'] == 1].index: label_num += 1 # 处理边界:避免索引越界,比如第一行前面无数据则从0开始 start_idx = max(0, idx - 2) end_idx = min(len(df)-1, idx + 1) # 给范围内的所有行赋值当前标签 df.loc[start_idx:end_idx, 'label'] = label_num
方法2:向量化操作(适合大数据集)
如果数据量较大,用掩码标记需打标签的行再批量赋值,效率更高:
import pandas as pd # 创建全False的掩码,标记需要打标签的行 mask = pd.Series(False, index=df.index) for idx in df[df['failure'] == 1].index: start = max(0, idx - 2) end = min(len(df)-1, idx + 1) mask.loc[start:end] = True # 为掩码覆盖的行分配递增标签 df['label'] = pd.NA current_label = 0 in_label_range = False for i in range(len(df)): if mask[i] and not in_label_range: current_label += 1 if mask[i]: df.loc[i, 'label'] = current_label in_label_range = mask[i]
补充说明
- 两种方法都会自动处理边界情况:比如故障行是第0行时,仅标记本行和后1行;故障行是最后一行时,仅标记前2行和本行;
- 若存在多个不重叠的故障区域,每个区域会获得递增的标签值(第一个区域标签为1,第二个为2,以此类推)。
内容的提问来源于stack exchange,提问作者Control Solution
相关产品推荐
相关产品推荐

