我发现结果有点随机。有时它是副本有时它是一个视图。例如:
df = pd.DataFrame([{'name':'Marry', 'age':21},{'name':'John','age':24}],index=['student1','student2'])
df
age name
student1 21 Marry
student2 24 John
现在,让我尝试稍微修改一下。
df2= df.loc['student1']
df2 [0] = 23
df
age name
student1 21 Marry
student2 24 John
如你所见,没有任何改变。 df2是一个副本。但是,如果我将另一名学生添加到数据框中...
df.loc['student3'] = ['old','Tom']
df
age name
student1 21 Marry
student2 24 John
student3 old Tom
尝试再次改变年龄..
df3=df.loc['student1']
df3[0]=33
df
age name
student1 33 Marry
student2 24 John
student3 old Tom
现在df3突然成了一个观点。到底是怎么回事?我想价值'旧'是关键?
通常,如果数据框具有单个dtype
,则可以获取视图,而原始数据框不是这种情况:
In [4]: df
Out[4]:
age name
student1 21 Marry
student2 24 John
In [5]: df.dtypes
Out[5]:
age int64
name object
dtype: object
但是,当你这样做时:
In [6]: df.loc['student3'] = ['old','Tom']
...:
第一列被强制转换为object
,因为列不能有混合dtypes:
In [7]: df.dtypes
Out[7]:
age object
name object
dtype: object
在这种情况下,底层的.values
将始终返回具有相同底层缓冲区的数组,对该数组的更改将反映在数据框中:
In [11]: vals = df.values
In [12]: vals
Out[12]:
array([[21, 'Marry'],
[24, 'John'],
['old', 'Tom']], dtype=object)
In [13]: vals[0,0] = 'foo'
In [14]: vals
Out[14]:
array([['foo', 'Marry'],
[24, 'John'],
['old', 'Tom']], dtype=object)
In [15]: df
Out[15]:
age name
student1 foo Marry
student2 24 John
student3 old Tom
另一方面,使用与原始数据框架类似的混合类型:
In [26]: df = pd.DataFrame([{'name':'Marry', 'age':21},{'name':'John','age':24}]
...: ,index=['student1','student2'])
...:
In [27]: vals = df.values
In [28]: vals
Out[28]:
array([[21, 'Marry'],
[24, 'John']], dtype=object)
In [29]: vals[0,0] = 'foo'
In [30]: vals
Out[30]:
array([['foo', 'Marry'],
[24, 'John']], dtype=object)
In [31]: df
Out[31]:
age name
student1 21 Marry
student2 24 John
但请注意,只有在可能成为视图的情况下才会返回视图,即如果它是正确的切片,否则,无论dtypes如何,都将进行复制:
In [39]: df.loc['student3'] = ['old','Tom']
In [40]: df2
Out[40]:
name
student3 Tom
student2 John
In [41]: df2.loc[:] = 'foo'
In [42]: df2
Out[42]:
name
student3 foo
student2 foo
In [43]: df
Out[43]:
age name
student1 21 Marry
student2 24 John
student3 old Tom
您将从一个DataFrame开始,该列具有两个具有两个不同dtypes的列:
df.dtypes
Out:
age int64
name object
dtype: object
由于不同的dtypes存储在引擎盖下的不同numpy数组中,因此您有两个不同的块:
df.blocks
Out:
{'int64': age
student1 21
student2 24, 'object': name
student1 Marry
student2 John}
如果您尝试对此DataFrame的第一行进行切片,则必须从每个不同的块中获取一个值,这使得必须创建一个副本。
df2.is_copy
Out[40]: <weakref at 0x7fc4487a9228; to 'DataFrame' at 0x7fc4488f9dd8>
在第二次尝试中,您正在更改dtypes。由于'old'不能存储在整数数组中,因此它将Series转换为对象Series。
df.loc['student3'] = ['old','Tom']
df.dtypes
Out:
age object
name object
dtype: object
现在,此DataFrame的所有数据都存储在一个块中(并在一个numpy数组中):
df.blocks
Out:
{'object': age name
student1 21 Marry
student2 24 John
student3 old Tom}
在此步骤中,可以在numpy数组上切片第一行而不创建副本,因此它返回一个视图。
df3._is_view
Out: True