2017-12-25 125 views
9

Tôi thấy kết quả là một chút ngẫu nhiên. Đôi khi đó là một bản sao đôi khi đó là một cái nhìn. Ví dụ:Ở Pandas, phương thức .iloc có cung cấp bản sao hoặc chế độ xem không?

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

df 
       age name 
    student1 21 Marry 
    student2 24 John 

Bây giờ, hãy để tôi cố gắng sửa đổi nó một chút.

df2= df.loc['student1'] 
df2 [0] = 23 
df 
       age name 
    student1 21 Marry 
    student2 24 John 

Như bạn có thể thấy, không có gì thay đổi. df2 là một bản sao. Tuy nhiên, nếu tôi thêm sinh viên khác vào dataframe ...

df.loc['student3'] = ['old','Tom'] 
df 
       age name 
    student1 21 Marry 
    student2 24 John 
    student3 old Tom 

Cố gắng thay đổi tuổi một lần nữa ..

df3=df.loc['student1'] 
df3[0]=33 
df 
       age name 
    student1 33 Marry 
    student2 24 John 
    student3 old Tom 

Bây giờ df3 đột nhiên trở thành một cái nhìn. Chuyện gì vậy? Tôi đoán giá trị 'cũ' là chìa khóa?

Trả lời

5

Nói chung, bạn có thể nhận được một cái nhìn nếu các dữ liệu-frame có một đơn dtype, đó là không trường hợp với ban đầu dữ liệu-frame của bạn:

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 

Tuy nhiên, khi bạn làm:

In [6]: df.loc['student3'] = ['old','Tom'] 
    ...: 

cột get đầu tiên của cưỡng chế object, kể từ cột không thể có dtypes hỗn hợp:

In [7]: df.dtypes 
Out[7]: 
age  object 
name object 
dtype: object 

Trong trường hợp này, cơ bản .values sẽ luôn trả về một mảng với bộ đệm cơ bản giống nhau, và thay đổi mảng đó sẽ được phản ánh trong dữ liệu khung:

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 

Mặt khác , với các loại hỗn hợp như với gốc dữ liệu-frame của bạn:

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 

Lưu ý, tuy nhiên, một cái nhìn sẽ chỉ được trả lại nếu nó có thể là một cái nhìn, tức là nếu nó là một lát thích hợp, nếu không , Một bản sao sẽ được thực hiện không phụ thuộc vào 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 
+0

Vậy điều đó có nghĩa là tôi sẽ luôn nhận được bản sao nếu khung dữ liệu có nhiều loại dtypes? – Qiyu

+0

@Qiyu với nhiều loại dtypes. –

+0

OK. Cảm ơn! – Qiyu

10

Bạn đang khởi động với một DataFrame rằng có hai cột với hai dtypes khác nhau:

df.dtypes 
Out: 
age  int64 
name object 
dtype: object 

Kể từ dtypes khác nhau được lưu trữ trong mảng NumPy khác nhau dưới mui xe, bạn có hai khối khác nhau đối với họ:

df.blocks 

Out: 
{'int64':   age 
student1 21 
student2 24, 'object':   name 
student1 Marry 
student2 John} 

Nếu bạn cố gắng cắt hàng đầu tiên của DataFrame này, nó phải nhận được một giá trị từ mỗi khối khác nhau mà làm cho nó cần thiết để tạo một bản sao.

df2.is_copy 
Out[40]: <weakref at 0x7fc4487a9228; to 'DataFrame' at 0x7fc4488f9dd8> 

Trong lần thử thứ hai, bạn đang thay đổi kiểu dtypes. Vì 'cũ' không thể được lưu trữ trong một mảng số nguyên, nó sẽ sử dụng Series như một chuỗi đối tượng.

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

df.dtypes 
Out: 
age  object 
name object 
dtype: object 

Bây giờ tất cả dữ liệu cho DataFrame này được lưu trữ trong một khối duy nhất (và trong một mảng NumPy đơn):

df.blocks 

Out: 
{'object':   age name 
student1 21 Marry 
student2 24 John 
student3 old Tom} 

Tại bước này, chém hàng đầu tiên có thể được thực hiện trên các mảng NumPy mà không tạo bản sao, vì vậy nó sẽ trả về một chế độ xem.

df3._is_view 
Out: True 
+0

Không bao giờ biết về 'df.blocks' –

+0

@ juanpa.arrivillaga tôi đã học được về nó từ [piRSquared] (https://stackoverflow.com/a/45805614/2285236) gần đây nhưng tôi nghĩ rằng họ sẽ biến nó thành một thuộc tính riêng. – ayhan

+0

'_is_view' là một chức năng thực sự tốt, tôi không biết về điều này. Cảm ơn –

Các vấn đề liên quan