在条件下设置pandas数据框的值

3
我无法找到与此查询类似的问题。但是,我有一个Pandas数据帧,我想使用其中两列进行条件判断,如果为真,则替换其中一列的值。
例如,我的其中一列是“itemname”,另一列是“value”。'itemname' 可能会重复多次。我想为每个 'itemname' 检查,如果所有具有相同名称的其他项目的值都为0,则将这些 'value' 替换为100。
我知道这应该很简单,但我无法理解它。
为使其更清晰,请看这里:
    itemname value
0      a       0
1      b       100
2      c       0
3      a       0
3      b       75
3      c       90

我希望将这个数据框转换成以下形式:
    itemname value
0      a       100
1      b       100
2      c       0
3      a       100
3      b       75
3      c       90

希望这能让您明白。我检查了是否有其他人提出了类似的问题,但在这种情况下找不到相关内容。

所以,如果同一项的所有值都等于0,您希望它们变为100? - Anton vBR
3个回答

3

您可以使用GroupBy+transform创建掩码。然后通过pd.DataFrame.loc和布尔索引进行分配:

mask = df.groupby('itemname')['value'].transform(lambda x: x.eq(0).all())
df.loc[mask.astype(bool), 'value'] = 100

print(df)

  itemname  value
0        a    100
1        b    100
2        c      0
3        a    100
3        b     75
3        c     90

3

使用transformany

df.loc[~df.groupby('itemname').value.transform('any'), 'value'] = 100

使用numpy.where函数:

s = ~df.groupby('itemname').value.transform('any')
df.assign(value=np.where(s, 100, df.value))

使用加法和乘法:

s = ~df.groupby('itemname').value.transform('any')
df.assign(value=df.value + (100 * s))

两种方法都能生成正确的输出,但是 np.where 和最终解决方案不会就地修改 DataFrame:
  itemname  value
0        a    100
1        b    100
2        c      0
3        a    100
3        b     75
3        c     90

说明

~df.groupby('itemname').value.transform('any')

0     True
1    False
2    False
3     True
3    False
3    False
Name: value, dtype: bool

由于 0 是一个假值,我们可以使用 any,并否定结果,来找到所有值都等于 0 的组。


3

如果您的所有值都是正数或0

可以使用transform和sum来检查是否为0:

m = (df.groupby('itemname').transform('sum') == 0)['value']
df.loc[m, 'value'] = 100

1
你可以有变量不全等于0,但它们的和仍为0。例如,你可以有一个值为“-50”,另一个值为“50”,因此总和为0,但这些值显然不等于 0 - Joe Patten
@JoePatten 你当然是对的。我在顶部添加了一个if语句。我只是假设数值为正数。 - Anton vBR
@jpp 加进去。 - Anton vBR
我认为(df.groupby('itemname').value.transform('sum') == 0)更安全(也更快),因为如果添加某一列时出现错误,你可能会遇到问题。 - user3483203
另外,在检查“sum”之前为什么不使用绝对值呢?这将使该解决方案也适用于负数。 - user3483203
@user3483203 是的,我考虑过这个问题,但那将是另一个计算操作,而且说实话,如果值>0,感觉没必要。通过进行列检查可以捕获虚假数据。但确实我也会采取abs解决方案。 - Anton vBR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接