2015-11-11 13 views
7

Dưới đây là một ví dụ về tối thiểu vấn đề của tôi làm việc:Pandas DataFrame chứa Nans sau phẫu thuật ghi

import pandas as pd 

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)]) 
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float') 
b = pd.Series([13.0, 15.0]) 

a.loc[1,'b'] = b # this line results in NaNs 
a.loc[1,'b'] = b.values # this yields correct behavior 

Tại sao việc chuyển nhượng đầu tiên không chính xác? Cả hai Series dường như có cùng một chỉ mục, vì vậy tôi cho rằng nó sẽ tạo ra kết quả chính xác.

Tôi đang sử dụng gấu trúc 0,17,0.

Trả lời

4

Khi bạn viết

a.loc[1,'b'] = b 

b là một Series, chỉ số của b có so sánh chính xác indexer tạo ra bởi a.loc[1,'b'] để cho các giá trị trong b được sao chép vào a. Hóa ra, tuy nhiên, khi a.columns là một MultiIndex, the indexer for a.loc[1,'b'] là:

(Pdb) p new_ix 
Index([(u'b', 0), (u'b', 1)], dtype='object') 

trong khi chỉ số cho b

(Pdb) p ser.index 
Int64Index([0, 1], dtype='int64') 

Họ không phù hợp, và do đó

(Pdb) p ser.index.equals(new_ix) 
False 

Vì các giá trị không được căn chỉnh, the code branch you fall into gán

(Pdb) p ser.reindex(new_ix).values 
array([ nan, nan]) 

Tôi thấy điều này bằng cách thêm pdb.set_trace() mã của bạn:

import pandas as pd 

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)]) 
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float') 
b = pd.Series([13.0, 15.0]) 
import pdb 
pdb.set_trace() 
a.loc[1,'b'] = b # this line results in NaNs 
a.loc[1,'b'] = b.values # this yields correct behavior 

và chỉ cần bước qua nó ở một "trình độ cao" và tìm the problem occurs in

 if isinstance(value, ABCSeries): 
      value = self._align_series(indexer, value) 

và sau đó bước qua nó một lần nữa (với một chiếc lược có răng mịn) với điểm ngắt bắt đầu từ đường dây gọi self._align_series(indexer, value).


Chú ý rằng nếu bạn thay đổi chỉ số của b cũng là một MultiIndex:

b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]])) 

sau đó

import pandas as pd 

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)]) 
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float') 
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]])) 
a.loc[1,'b'] = b 
print(a) 

mang

a  b  c 
    0 1 0 1 0 1 
0 0 0 0 0 0 0 
1 0 0 13 15 0 0 
2 0 0 0 0 0 0 
+0

Trong trường hợp của tôi, 'b' thực sự là một chuỗi tạm thời thu được từ việc cắt một DataFrame khác (không có MultiIndex). Có cách nào để giải quyết điều này mà không lưu trữ Series tạm thời đó và tái tạo nó không? – MindV0rtex

+0

Tôi nghĩ cách giải quyết đơn giản nhất là cách bạn đã hiển thị - chỉ định đối tượng không được lập chỉ mục: 'a.loc [1, 'b'] = b.values'. – unutbu

1

Bạn có thể trực tiếp gán b đến một cột trong a, bởi vì b không phải là một Loạt đa điểm.Thay đổi b sẽ làm cho nó hoạt động:

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)]) 
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float') 
index = pd.MultiIndex.from_product([['b'], range(2)]) 
b = pd.Series([13.0, 15.0], index=index) 

a.loc[1,'b'] = b 
print(a) 

mang

a  b  c 
    0 1 0 1 0 1 
0 0 0 0 0 0 0 
1 0 0 13 15 0 0 
2 0 0 0 0 0 0 

Các trường hợp khác, nơi bạn sử dụng b.values, khả năng làm việc vì Pandas mất các giá trị trong b theo mệnh giá, và cố gắng thực hiện nhiệm vụ logic nhất cho các giá trị được cung cấp.