如何在DataFrame中按主体提取最后一个目标字符串对应值及其上一行值?
我来帮你搞定这个需求!针对每个主体提取最后一个green对应的value以及它上一行的value,用pandas可以轻松实现,下面是具体的步骤和代码示例:
解决思路与实现
核心思路
我们可以按subject分组后,对每个组单独处理:
- 先定位组内所有
type为green的行,找到最后一行的位置; - 根据这个位置,提取该行的
value(即last_green),同时提取上一行的value(即before_last_green); - 最后把每个组的结果汇总成你需要的格式。
代码实现(自定义函数版)
这种方式逻辑清晰,容易理解,适合新手:
首先导入pandas并构造你的示例数据:
import pandas as pd # 构造示例DataFrame data = { 'subject': [111, 111, 111, 111, 111, 222, 222, 222, 222, 222], 'type': ['yellow', 'green', 'yellow', 'blue', 'green', 'blue', 'green', 'yellow', 'blue', 'yellow'], 'value': [354, 584, 584, 492, 493, 459, 583, 539, 392, 394] } dat1 = pd.DataFrame(data)
然后定义一个处理单个分组的函数,再用groupby().apply()应用到每个组:
def extract_green_values(group): # 筛选当前组所有type为green的行的索引 green_rows = group[group['type'] == 'green'] if green_rows.empty: # 如果组里没有green行,返回空值 return pd.Series({'last_green': pd.NA, 'before_last_green': pd.NA}) # 取最后一个green的行 last_green = green_rows.iloc[-1] last_green_value = last_green['value'] # 获取上一行的值(要确保不是组的第一行) last_green_index = last_green.name if last_green_index > group.index[0]: before_last_green_value = group.loc[last_green_index - 1, 'value'] else: # 若第一个行就是green,没有上一行,设为缺失值 before_last_green_value = pd.NA return pd.Series({'last_green': last_green_value, 'before_last_green': before_last_green_value}) # 分组处理并整理结果 result = dat1.groupby('subject').apply(extract_green_values).reset_index() print(result)
输出结果
运行代码后,会得到你期望的结果:
subject last_green before_last_green 0 111 493 492 1 222 583 459
高效优化版(无需自定义函数)
如果你的数据量很大,想追求更高效率,可以用这种更简洁的写法:
# 给每个组内的行分配序号(从0开始) dat1['row_in_group'] = dat1.groupby('subject').cumcount() # 找到每个组最后一个green的行序号 last_green_pos = dat1[dat1['type'] == 'green'].groupby('subject')['row_in_group'].max() # 合并信息,筛选目标行和上一行 merged_data = dat1.merge(last_green_pos, on='subject', suffixes=('', '_last')) target_rows = merged_data[ (merged_data['row_in_group'] == merged_data['row_in_group_last']) | (merged_data['row_in_group'] == merged_data['row_in_group_last'] - 1) ] # 分组提取对应值 result = target_rows.groupby('subject').agg( last_green=('value', lambda x: x.iloc[-1]), before_last_green=('value', lambda x: x.iloc[0] if len(x)>=2 else pd.NA) ).reset_index() print(result)
这个方法同样能得到相同的结果,且避免了自定义函数的额外开销,处理大数据集时更高效。
内容的提问来源于stack exchange,提问作者Viola Hollestein
相关产品推荐
相关产品推荐

