2015-03-19 24 views
10

Tôi có một khung dữ liệu với Multiindex và muốn sửa đổi một mức cụ thể của Multiindex. Ví dụ, mức độ đầu tiên có thể là chuỗi và tôi có thể muốn loại bỏ các khoảng trống màu trắng từ đó mức độ index:Pandas: Sửa đổi một cấp độ cụ thể của Multiindex

df.index.levels[1] = [x.replace(' ', '') for x in df.index.levels[1]] 

Tuy nhiên, các mã trên kết quả trong một lỗi:

TypeError: 'FrozenList' does not support mutable operations. 

Tôi biết tôi có thể reset_index và sửa đổi cột và sau đó tái tạo Multiindex, nhưng tôi tự hỏi liệu có một cách thanh lịch hơn để sửa đổi một cấp độ cụ thể của Multiindex trực tiếp không.

+1

Không, chỉ là không thay đổi. Nếu bạn muốn thay đổi nó, bạn phải làm lại nó. – tnknepp

+1

http://stackoverflow.com/a/26629643/2230844 – denfromufa

Trả lời

10

Như đã đề cập trong các ý kiến, chỉ số là không thay đổi và phải làm lại khi sửa đổi, nhưng bạn không cần phải sử dụng reset_index cho rằng, bạn có thể tạo mới đa-index trực tiếp:

df.index = pd.MultiIndex.from_tuples([(x[0], x[1].replace(' ', ''), x[2]) for x in df.index]) 

Ví dụ này dành cho chỉ mục 3 cấp, nơi bạn muốn sửa đổi cấp trung bình. Bạn cần thay đổi kích thước của bộ tuple cho các kích thước cấp độ khác nhau.

1

Nhờ @ bình luận cxrodgers, tôi nghĩ rằng cách nhanh nhất để làm điều này là:

df.index = df.index.set_levels(df.index.levels[0].str.replace(' ', ''), level=0) 

Cũ, còn câu trả lời:

tôi thấy rằng danh sách hiểu được đề xuất bởi các công trình @Shovalt nhưng cảm thấy chậm trên máy của tôi (sử dụng một khung dữ liệu với> 10.000 hàng).

Thay vào đó, tôi đã có thể sử dụng phương thức .set_levels, nhanh hơn một chút đối với tôi.

%timeit pd.MultiIndex.from_tuples([(x[0].replace(' ',''), x[1]) for x in df.index]) 
1 loop, best of 3: 394 ms per loop 

%timeit df.index.set_levels(df.index.get_level_values(0).str.replace(' ',''), level=0) 
10 loops, best of 3: 134 ms per loop 

Thực tế, tôi chỉ cần thêm một số văn bản vào trước. Đây thậm chí còn nhanh hơn với .set_levels:

%timeit pd.MultiIndex.from_tuples([('00'+x[0], x[1]) for x in df.index]) 
100 loops, best of 3: 5.18 ms per loop 

%timeit df.index.set_levels('00'+df.index.get_level_values(0), level=0) 
1000 loops, best of 3: 1.38 ms per loop 

%timeit df.index.set_levels('00'+df.index.levels[0], level=0) 
1000 loops, best of 3: 331 µs per loop 

giải pháp này được dựa trên câu trả lời trong các liên kết từ những nhận xét của @denfromufa ...

python - Multiindex and timezone - Frozen list error - Stack Overflow

+0

Điều này có vẻ nhanh hơn và thanh lịch hơn việc xây dựng một chỉ mục mới. Tôi cũng sẽ thêm rằng trong hầu hết trường hợp, bạn sẽ chỉ làm 'inplace = True'. – cxrodgers

+0

Thực ra tôi nghĩ rằng mã của bạn có lỗi, nó phải là 'df.index.levels [0]' ở bất cứ đâu bạn có 'df.index.get_level_values ​​(0)'. Đây cũng là cách họ làm điều đó trong câu trả lời mà bạn liên kết – cxrodgers

+0

Có phải '.get_level_values' không có sẵn cho bạn không? Bạn đang sử dụng phiên bản gấu trúc nào? Tôi đang trên v0.22.0 và cả hai dường như cho tôi kết quả tương tự, nhưng đề xuất của bạn chỉ đơn giản là '.levels [0]' nhanh hơn '.get_level_values ​​(0)'. Tôi sẽ thêm điều này vào câu trả lời của tôi. – John

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