我很难找到一个错误,基本上可以归结为以下事实:
中的第三行import pandas as pd
df = pd.DataFrame({'a':range(4),'b':np.random.random(4)})
df.values[1:-1] = [[0.1]*2]*2
没有效果——所有行都没有改变。 虽然阻止我将整数更改为 float 至少有一定意义(尽管我希望能够规避这一点),但这似乎并不是这种行为背后的原因
df.values[1:-1,1] = [0.1]*2
也没有效果!奇怪的是
中的第三行import pandas as pd
df = pd.DataFrame({'a':range(4))})
df.values[1:-1] = [[0.1]]*2
确实有效果,尽管仍然不是您期望的效果——相应的条目被设置为零!同样,这有点道理,但我宁愿得到一个异常,也不愿得到隐式整数转换。
我认为这种行为应该改变,或者至少 pandas 应该警告我它忽略了我告诉它做的事情。然而,在我去 github 存储库上打开一个有关它的问题之前,我首先想征求其他意见,更重要的是,我想问:
如何可靠地更改 DataFrame 的子集(行和列)以获取给定 numpy 数组的值 (我知道这是一种黑客行为,但这就是我的数据世界)
最佳答案
首先不要调用.values
来分配数据。
行为差异的原因是在您的第一个示例中:
df = pd.DataFrame({'a':range(4),'b':np.random.random(4)})
column 'b'
是作为数据参数传递的 numpy 数组的 View ,因为构造函数识别出这是一个 numpy 数组,出于效率原因, block 管理器可以查看数组(无需重建数组并复制数据)。
当您调用.values
时,这可能会也可能不会返回基础数据的 View 。
当我们调用.values
时:
In[92]:
df.values
Out[92]:
array([[0. , 0.02512956],
[1. , 0.7394139 ],
[2. , 0.7535009 ],
[3. , 0.60658149]])
这是数据的 numpy 表示,它可能是也可能不是真实底层数据的 View 。
就您而言,它返回的是副本而不是 View ,因此原因是:
df.values[1:-1] = [[0.1]*2]*2
不起作用。
但是,如果您使用iloc
,那么它确实有效:
df.iloc[1:-1] = [[0.1]*2]*2
在第二个 df 中,您仅传递一个范围,因此数据是在内部构造的,与传递 numpy 数组时不同,不会对传递的数据进行 View 。当您调用 .values
时,它会返回数据 View ,并且它恰好可以工作,但不能保证它可以工作。这是不好的做法,您应该避免这种歧义。
关于python - 为什么赋值会默默地失败或做错误的事情,我怎样才能阻止它这样做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55709890/