如何在Pandas DataFrame中计算同组特定行的字段差值
解决DataFrame中分组计算与特定基准行差值的问题
你遇到的问题是因为diff()方法默认计算的是组内连续行的差值,而不是和指定的基准行(field1='start'的行)做差。这里有两种简洁的方法可以实现你的需求:
方法一:使用groupby.transform直接广播基准值
这种方法可以在分组后直接将每个组的基准值广播到所有行,再计算差值:
import pandas as pd # 构造你的示例DataFrame data = {'sid':[1,1,1,2,2,2], 'field1':['start', None, None, 'start', None, None], 'field2':['a', 'b', 'z', 'd', 'z','s'], 'val':[20, 22, 23, 40, 45, 47]} df = pd.DataFrame(data) # 为每个sid分组,提取field1='start'对应的val作为基准值并广播到全组 base_vals = df.groupby('sid')['val'].transform( lambda x: x[df.loc[x.index, 'field1'] == 'start'].iloc[0] ) # 计算当前val与基准值的差值 df['newval'] = df['val'] - base_vals # 将field1='start'的行的newval设为NaN df.loc[df['field1'] == 'start', 'newval'] = pd.NA print(df)
方法二:先提取基准值字典再匹配
如果每个sid确定只有一个field1='start'的行,这种方法更直观:
import pandas as pd data = {'sid':[1,1,1,2,2,2], 'field1':['start', None, None, 'start', None, None], 'field2':['a', 'b', 'z', 'd', 'z','s'], 'val':[20, 22, 23, 40, 45, 47]} df = pd.DataFrame(data) # 提取每个sid对应的start行的val值,存入字典 start_val_map = df[df['field1'] == 'start'].set_index('sid')['val'].to_dict() # 为每行匹配对应的基准值 df['base_val'] = df['sid'].map(start_val_map) # 计算差值并处理start行 df['newval'] = df['val'] - df['base_val'] df.loc[df['field1'] == 'start', 'newval'] = pd.NA # 可选:删除中间的base_val列 df = df.drop('base_val', axis=1) print(df)
两种方法都会得到你预期的结果:
sid field1 field2 val newval 0 1 start a 20 NaN 1 1 None b 22 2.0 2 1 None z 23 3.0 3 2 start d 40 NaN 4 2 None z 45 5.0 5 2 None s 47 7.0
为什么之前的diff()不适用?
df.groupby('sid')['val'].diff()计算的是组内当前行与前一行的差值,比如第2行的23-22=1,这和你需要的与组内基准行(start行)做差的逻辑不符,所以会得到不符合预期的结果。
内容的提问来源于stack exchange,提问作者Bhavana
相关产品推荐
相关产品推荐

