在分组的熊猫df中使用IF-THEN创建新列

时间:2019-07-22 18:21:48

标签: pandas

我正在将简单函数应用于已分组的df。下面是我正在尝试的。即使我尝试将功能修改为仅执行一个步骤,我仍然会遇到相同的错误。任何方向都将非常有帮助。

def udf_pd(df_group):
if (df_group['A'] - df_group['B']) > 1:
    df_group['D'] = 'Condition-1'
elif df_group.A == df_group.C:
    df_group['D'] = 'Condition-2'
else:
    df_group['D'] = 'Condition-3'

return df_group

final_df = df.groupby(['id1','id2']).apply(udf_pd)
final_df = final_df.reset_index()


ValueError: The truth value of a Series is ambiguous. Use a.empty, 
a.bool(), a.item(), a.any() or a.all().

2 个答案:

答案 0 :(得分:2)

请注意,在 groupby.apply 中,该功能将应用于整个组。 另一方面,每个 if 条件必须归结为单个值 (不适用于 True / False 值的任何 Series )。

因此此函数中2列的每次比较都必须补充 例如 all() any(),如下例所示:

def udf_pd(df_group):
    if (df_group.A - df_group.B > 1).all():
        df_group['D'] = 'Condition-1'
    elif (df_group.A == df_group.C).all():
        df_group['D'] = 'Condition-2'
    else:
        df_group['D'] = 'Condition-3'
    return df_group

当然,该函数可以返回整个组,例如“扩展” 按新列,在这种情况下,新列的单个值 是广播,因此当前组中的每一行都会收到该值。

我创建了一个测试DataFrame:

   id1  id2  A  B  C
0    1    1  5  3  0
1    1    1  7  5  4
2    1    2  3  4  3
3    1    2  4  5  4
4    2    1  2  4  3
5    2    1  4  5  4    

在此示例中:

  • 在第一组( id1 == 1 id2 == 1 )中,在所有行 A-B> 1 中, 所以 Condition-1 True
  • 在第二组( id1 == 1 id2 == 2 )中,上述条件为 满足,但在所有行中, A == C ,因此 Condition-2 True
  • 在最后一组( id1 == 2 id2 == 1 )中,以上都不是 满足条件,所以 Condition-3 True

因此df.groupby(['id1','id2']).apply(udf_pd)的结果是:

   id1  id2  A  B  C            D
0    1    1  5  3  0  Condition-1
1    1    1  7  5  4  Condition-1
2    1    2  3  4  3  Condition-2
3    1    2  4  5  4  Condition-2
4    2    1  2  4  3  Condition-3
5    2    1  4  5  4  Condition-3

答案 1 :(得分:1)

我之前遇到过此错误,但我对熊猫的理解并不确定应该对哪个值运行条件。您可能要使用.any().all()。考虑这些示例

>>> a = pd.Series([0,0,3])
>>> b = pd.Series([1,1,1])
>>> a - b
0   -1
1   -1
2    2
dtype: int64

>>> (a - b) >= 1
0    False
1    False
2     True
dtype: bool

您会看到(a-b)> = 1真实性有点含糊,向量中的第一个元素为false,而其他元素为true。

使用.any().all()将评估整个系列。

>>> ((a - b) >= 1).any()
True
>>> ((a - b) >= 1).all()
False

.any()检查该系列中的所有元素是否都为True。 .all()会检查所有所有元素是否为True。在本例中不是。

您也可以查看此帖子以获取更多信息:Pandas Boolean .any() .all()