在数据框中添加一列,对现有列的不同行执行不同的操作
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
的行掩码
然后用 c
和 Series.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
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
的行掩码
然后用 c
和 Series.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