如何用Pandas替代循环实现前置值条件的序列值标记
当然有更简洁的Pandas原生实现方式!这种场景用Pandas的矢量化操作替代循环,不仅代码更清爽,处理大数据量时效率也会高很多。
问题回顾
我们需要给一个Pandas Series标记符合以下条件的元素为True:
- 当前元素包含
input且不包含unexpected - 它的前一个元素包含
unexpected
其余元素统一标记为False。
示例数据与期望结果
首先先明确我们的输入和目标输出:
输入Series
import pandas as pd s = pd.Series({ 0: 'feedback ratings-positive-unexpected origin', 1: 'decision-tree identified-regex input', 2: 'feedback ratings-options input', 3: 'feedback ratings-options-unexpected origin', 4: 'checkout order-placed input', 5: 'decision-tree identified-regex input' })
期望标记结果
want = pd.Series({ 0: False, 1: True, 2: False, 3: False, 4: True, 5: False })
你已有的循环实现
import numpy as np mapi = [] for i in np.arange(s.shape[0]): if 'input' in s.iloc[i] and 'unexpected' not in s.iloc[i]: if 'unexpected' in s.iloc[i-1]: mapi.append(True) else: mapi.append(False) else: mapi.append(False)
Pandas矢量化解决方案
我们可以利用Pandas的字符串方法和移位操作来实现完全矢量化的逻辑,代码简洁且高效:
# 1. 拆分并定义三个核心布尔条件 # 当前元素包含input current_has_input = s.str.contains('input') # 当前元素不包含unexpected current_no_unexpected = ~s.str.contains('unexpected') # 前一个元素包含unexpected,移位后第一个元素为NaN,用na=False标记为False prev_has_unexpected = s.shift(1).str.contains('unexpected', na=False) # 2. 组合三个条件得到最终标记结果 result = current_has_input & current_no_unexpected & prev_has_unexpected
代码解释
s.str.contains():Pandas专门处理字符串的方法,能批量检查每个元素是否包含指定子串,返回布尔Seriess.shift(1):把原Series的元素向下移动一位,这样每个位置上的值就变成了原Series中前一个位置的元素,第一个位置会变成NaNna=False:针对移位后出现的NaN,直接标记为False(因为第一个元素没有前一个元素,肯定不满足条件)&:逻辑与操作,只有三个条件同时满足时,结果才为True
你可以验证一下结果是否和期望一致:
print(result.equals(want)) # 输出: True
内容的提问来源于stack exchange,提问作者INGl0R1AM0R1
相关产品推荐
相关产品推荐

