使用.loc赋值时Pandas DataFrame出现意外结果
我在用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