使用.loc赋值时Pandas DataFrame出现意外结果

4 投票
1 回答
8923 浏览
提问于 2025-04-18 08:33

我在用pandas做一些计算,发现使用.loc方法的结果有点意外。我不确定是我用错了语法,还是遇到了bug。

df = pd.DataFrame(index=['series1', 'series2', 'series3'])
df['prev value/unit'] = [99,99,99]
df['value'] = [100,100,100]
df['units'] = [100,100,0]
df['value/unit'] = df['value']/df['units']

我创建了一个数据框,其中会出现一些除以零的情况,如下所示。根据业务逻辑,如果出现了除以零的情况,就应该使用之前的值或单位。

         prev value/unit  value  units  value/unit
series1               99    100    100    1.000000
series2               99    100    100    1.000000
series3               99    100      0         inf

所以我添加了:

df.loc[df.units == 0, 'value/unit'] = df['prev value/unit']

这样做的效果是好的,之前的无穷大值被正确地替换成了99(之前的每单位值)。

但是如果没有除以零的情况。

df.loc[df.units == 0, 'value/unit']
#is a empty Series
#Series([], name: value/unit, dtype: float64)

然后把 df['prev value/unit'] 赋值给它,结果却把所有的值都覆盖掉了!!!!

比如说:

df = pd.DataFrame(index=['series1', 'series2', 'series3'])
df['prev value/unit'] = [99,99,99]
df['value'] = [100,100,100]
df['units'] = [100,100,100]
df['value/unit'] = df['value']/df['units']
df.loc[df.units == 0, 'value/unit'] = df['prev value/unit']

结果是:

         prev value/unit  value  units  value/unit
series1               99    100    100          99
series2               99    100    100          99
series3               99    100    100          99

这完全出乎我的意料。我是无意中用错了 .loc 的语法,还是说这是个bug?我特别使用它是为了避免给数据框的临时视图赋值。顺便提一下,我用的是pandas 0.13.1。

1 个回答

5

我猜这可能跟视图或副本有关,但看起来确实有点出乎意料的行为——你可以在github上提个问题。

https://github.com/pydata/pandas/issues

另一种写代码的方法是使用numpy.where,比如:

In [86]: import numpy as np
In [87]: df['value/unit'] = np.where(df['units'] == 0, df['prev value/unit'], df['value']/df['units'])

In [88]: df
Out[87]: 
         prev value/unit  value  units  value/unit
series1               99    100    100           1
series2               99    100    100           1
series3               99    100    100           1

撰写回答