为什么分配了“无”时会创建副本?

2024-04-25 14:14:33 发布

您现在位置:Python中文网/ 问答频道 /正文

In[216]: foo = pd.DataFrame({'a':[1,2,3], 'b':[3,4,5]})
In[217]: bar = foo.ix[:1]
In[218]: bar
Out[218]: 
   a  b
0  1  3
1  2  4

视图按预期创建。你知道吗

In[219]: bar['a'] = 100
In[220]: bar
Out[220]: 
     a  b
0  100  3
1  100  4
In[221]: foo
Out[221]: 
     a  b
0  100  3
1  100  4
2    3  5

如果视图被修改,那么原始的数据帧foo也会被修改。 但是,如果作业没有完成,那么似乎要复制一份。 有人能解释一下发生了什么,也许还有背后的逻辑吗?你知道吗

In[222]: bar['a'] = None
In[223]: bar
Out[223]: 
      a  b
0  None  3
1  None  4
In[224]: foo
Out[224]: 
     a  b
0  100  3
1  100  4
2    3  5

Tags: 数据innone视图dataframefoo作业bar
2条回答

分配bar['a'] = None时,强制列将其数据类型从I4更改为object。你知道吗

这样做会强制它为列分配一个新的object数组,然后它当然会写入该新数组,而不是写入与原始DataFrame共享的旧数组。你知道吗

你正在做一种链式作业,请看here为什么这是个非常糟糕的主意。你知道吗

看看这个问题here

Pandas通常会警告您正在修改视图(在0.15.0中更是如此)。你知道吗

In [49]: foo = pd.DataFrame({'a':[1,2,3], 'b':[3,4,5]})

In [51]: foo
Out[51]: 
   a  b
0  1  3
1  2  4
2  3  5

In [52]: bar = foo.ix[:1]

In [53]: bar
Out[53]: 
   a  b
0  1  3
1  2  4

In [54]: bar.dtypes
Out[54]: 
a    int64
b    int64
dtype: object

# this is an internal method (but is for illustration)
In [56]: bar._is_view
Out[56]: True

# this will warn in 0.15.0
In [57]: bar['a'] = 100
/usr/local/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  #!/usr/local/bin/python

In [58]: bar._is_view
Out[58]: True

# bar is now a copied object (and will replace the existing dtypes with new ones).
In [59]: bar['a'] = None

In [60]: bar.dtypes
Out[60]: 
a    object
b     int64
dtype: object

你应该永远不要依赖某个东西是否是一个视图(即使在numpy中),除非在某些非常有效的情况下。它不是一个保证的构造,这取决于底层数据的内存布局。你知道吗

您应该很少尝试设置通过视图传播的数据。在pandas中这样做几乎总是会在混合数据类型时引起麻烦。(在numpy中,您只能对单个数据类型拥有视图;我甚至不确定在一个多数据类型数组中更改数据类型的视图是什么,或者它是否被允许)。你知道吗

相关问题 更多 >