在Pandas中,.iloc方法是否提供副本或视图?

Qiy*_*iyu 16 python dataframe pandas

我发现结果有点随机.有时它是副本有时它是一个视图.例如:

df = pd.DataFrame([{'name':'Marry', 'age':21},{'name':'John','age':24}],index=['student1','student2'])

df
              age   name
   student1   21  Marry
   student2   24   John
Run Code Online (Sandbox Code Playgroud)

现在,让我尝试稍微修改一下.

df2= df.loc['student1']
df2 [0] = 23
df
              age   name
   student1   21  Marry
   student2   24   John
Run Code Online (Sandbox Code Playgroud)

如你所见,没有任何改变.df2是一个副本.但是,如果我将另一名学生添加到数据框中...

df.loc['student3'] = ['old','Tom']
df
               age   name
    student1   21  Marry
    student2   24   John
    student3  old    Tom
Run Code Online (Sandbox Code Playgroud)

尝试再次改变年龄..

df3=df.loc['student1']
df3[0]=33
df
               age   name
    student1   33  Marry
    student2   24   John
    student3  old    Tom
Run Code Online (Sandbox Code Playgroud)

现在df3突然成了一个观点.到底是怎么回事?我想价值'旧'是关键?

ayh*_*han 15

您将从一个DataFrame开始,该列具有两个具有两个不同dtypes的列:

df.dtypes
Out: 
age      int64
name    object
dtype: object
Run Code Online (Sandbox Code Playgroud)

由于不同的dtypes存储在引擎盖下的不同numpy数组中,因此您有两个不同的块:

df.blocks

Out: 
{'int64':           age
 student1   21
 student2   24, 'object':            name
 student1  Marry
 student2   John}
Run Code Online (Sandbox Code Playgroud)

如果您尝试对此DataFrame的第一行进行切片,则必须从每个不同的块中获取一个值,这使得必须创建一个副本.

df2.is_copy
Out[40]: <weakref at 0x7fc4487a9228; to 'DataFrame' at 0x7fc4488f9dd8>
Run Code Online (Sandbox Code Playgroud)

在第二次尝试中,您正在更改dtypes.由于'old'不能存储在整数数组中,因此它将Series转换为对象Series.

df.loc['student3'] = ['old','Tom']

df.dtypes
Out: 
age     object
name    object
dtype: object
Run Code Online (Sandbox Code Playgroud)

现在,此DataFrame的所有数据都存储在一个块中(并在一个numpy数组中):

df.blocks

Out: 
{'object':           age   name
 student1   21  Marry
 student2   24   John
 student3  old    Tom}
Run Code Online (Sandbox Code Playgroud)

在此步骤中,可以在numpy数组上切片第一行而不创建副本,因此它返回一个视图.

df3._is_view
Out: True
Run Code Online (Sandbox Code Playgroud)


jua*_*aga 6

通常,如果数据框具有单个数据框,则可以获取视图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
Run Code Online (Sandbox Code Playgroud)

但是,当你这样做时:

In [6]: df.loc['student3'] = ['old','Tom']
   ...:
Run Code Online (Sandbox Code Playgroud)

第一列被强制执行object,因为列不能具有混合dtypes:

In [7]: df.dtypes
Out[7]:
age     object
name    object
dtype: object
Run Code Online (Sandbox Code Playgroud)

在这种情况下,底层.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
Run Code Online (Sandbox Code Playgroud)

另一方面,使用与原始数据框架类似的混合类型:

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
Run Code Online (Sandbox Code Playgroud)

但请注意,只有在可能成为视图的情况下才会返回视图,即如果它是一个合适的切片,否则,无论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
Run Code Online (Sandbox Code Playgroud)

  • 那么这是否意味着如果数据框有多个dtypes,我将始终获得副本? (2认同)