在数据框中添加一列,对现有列的不同行执行不同的操作

Adding a column in a dataframe doing different operation for different rows of existing column

FOOD_ID   SAMPLE_NO   ELEMENT1   ELEMENT2   ELEMENT3
 F110       A1          0.4        0.2        0.1
 F110       A2          0.6        0.1        0.3
 F110       B1          0.4        0.3        0.7
 F110       B2          0.5        0.6        0.9
 F110       C1          0.5        0.3        0.4
 F110       C2          0.6        0.2        0.6
 F110       C3          0.1        0.1        0.5
 F120       B1          0.4        0.2        0.2
 F120       B2          0.5        0.2        0.5
 F120       B3          0.7        0.3        0.8
 F120       B4          0.7        0.7        0.9
 F120       B5          0.2        0.9        0.1

我的数据如上所示。我想添加列,为食物 ID 提供元素 1、2、3 的平均值。 如果样本 C 可用,则平均值将只是 C 样本的平均值,如果 C 样本不存在,则平均值将只是 B 样本的最新值。

对于存在 f110 C 样本的食物,这就是为什么平均值将是 C 样本的平均值。 对于食品 f120 C 样本不存在,这就是为什么 B 样本 B5 的平均值是最新的。

我最终想要的数据框如下所示...

FOOD_ID   ELEMENT1_AVG          ELEMENT2_AVG       ELEMENT3_AVG
F110     (0.5+0.6+0.1)/3=0.4  (0.3+0.2+0.1)=0.2  (0.4+0.6+0.5)=0.5
F120         0.2                    0.9               0.1

需要帮助。 提前致谢。

您可以通过 Series.str.startswith, for last B first test if not exist C per group with GroupBy.transform and GroupBy.any to m and invert mask by ~, chain with b and filter by df[(~m & b)], and then get last B by Series.duplicated 和反转 ~.

获得具有 C 的行掩码

然后用 cSeries.combine_first 过滤原始 DataFrame 并聚合 mean,因为 B 每组只有一行 return 相同的值:

c = df['SAMPLE_NO'].str.startswith('C')
b = df['SAMPLE_NO'].str.startswith('B')
m = c.groupby(df['FOOD_ID']).transform('any')

mask = ~df[(~m & b)].duplicated(subset=['FOOD_ID'], keep='last')
df1 = (df[mask.combine_first(c)]
              .groupby('FOOD_ID')
              .mean()
              .add_suffix('_AVG')
              .reset_index())
print (df1)
  FOOD_ID  ELEMENT1_AVG  ELEMENT2_AVG  ELEMENT3_AVG
0    F110           0.4           0.2           0.5
1    F120           0.2           0.9           0.1