2013-12-11 20 views
10

Tạo dataframe tôi:giá trị chỉ số Đổi tên trong dataframe multiindex

from pandas import * 
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], 
      ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] 

tuples = zip(*arrays) 

index = MultiIndex.from_tuples(tuples, names=['first','second']) 
data = DataFrame(randn(8,2),index=index,columns=['c1','c2']) 

data 
Out[68]: 
        c1  c2 
first second      
bar one  0.833816 -1.529639 
     two  0.340150 -1.818052 
baz one -1.605051 -0.917619 
     two -0.021386 -0.222951 
foo one  0.143949 -0.406376 
     two  1.208358 -2.469746 
qux one -0.345265 -0.505282 
     two  0.158928 1.088826 

Tôi muốn đổi tên "đầu tiên" giá trị chỉ số, chẳng hạn như "thanh" -> "con mèo", "baz" -> "con chó ", vv Tuy nhiên, mỗi ví dụ tôi đã đọc hoặc hoạt động trên một chỉ số duy nhất cấp và/hoặc vòng thông qua toàn bộ chỉ mục để có hiệu quả tái tạo nó từ đầu. Tôi đã suy nghĩ một điều gì đó như:

data = data.reindex(index={'bar':'cat','baz':'dog'}) 

nhưng điều này không hiệu quả, cũng như tôi thực sự mong đợi nó hoạt động trên nhiều chỉ mục. Tôi có thể thực hiện thay thế đó mà không cần lặp qua toàn bộ chỉ mục dataframe không?

Bắt đầu chỉnh sửa

Tôi do dự để cập nhật 0.13 cho đến khi phát hành, vì vậy tôi đã sử dụng workaround sau:

index = data.index.tolist() 
for r in xrange(len(index)): 
    index[r] = (codes[index[r][0]],index[r][1]) 

index = pd.MultiIndex.from_tuples(index,names=data.index.names) 
data.index = index 

đâu là một từ điển được xác định trước mã: cặp chuỗi. Điều này thực sự không phải là lớn của một hiệu suất của mình như tôi đã mong đợi (mất một vài giây để hoạt động trên ~ 1,1 triệu hàng). Nó không phải là đẹp như một lớp lót, nhưng nó hoạt động.

End Sửa

+1

Đây hiện là đề xuất nâng cao cho phiên bản tương lai của gấu trúc: https://github.com/pydata/pandas/issues/4160 (@unutbu soln hoạt động qua ATM) – Jeff

Trả lời

16

Sử dụng set_levels phương pháp (new in version 0.13.0):

data.index.set_levels([[u'cat', u'dog', u'foo', u'qux'], 
         [u'one', u'two']], inplace=True) 

sản lượng

    c1  c2 
first second      
cat one -0.289649 -0.870716 
     two -0.062014 -0.410274 
dog one  0.030171 -1.091150 
     two  0.505408 1.531108 
foo one  1.375653 -1.377876 
     two -1.478615 1.351428 
qux one  1.075802 0.532416 
     two  0.865931 -0.765292 

Để remap một mức độ dựa trên một dict, bạn có thể sử dụng một chức năng như thế này:

def map_level(df, dct, level=0): 
    index = df.index 
    index.set_levels([[dct.get(item, item) for item in names] if i==level else names 
         for i, names in enumerate(index.levels)], inplace=True) 

dct = {'bar':'cat', 'baz':'dog'} 
map_level(data, dct, level=0) 

Dưới đây là một ví dụ Runnable:

import numpy as np 
import pandas as pd 

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], 
      ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] 
tuples = zip(*arrays) 
index = pd.MultiIndex.from_tuples(tuples, names=['first','second']) 
data = pd.DataFrame(np.random.randn(8,2),index=index,columns=['c1','c2']) 
data2 = data.copy() 

data.index.set_levels([[u'cat', u'dog', u'foo', u'qux'], 
         [u'one', u'two']], inplace=True) 
print(data) 
#      c1  c2 
# first second      
# cat one  0.939040 -0.748100 
#  two -0.497006 -1.185966 
# dog one -0.368161 0.050339 
#  two -2.356879 -0.291206 
# foo one -0.556261 0.474297 
#  two  0.647973 0.755983 
# qux one -0.017722 1.364244 
#  two  1.007303 0.004337 

def map_level(df, dct, level=0): 
    index = df.index 
    index.set_levels([[dct.get(item, item) for item in names] if i==level else names 
         for i, names in enumerate(index.levels)], inplace=True) 
dct = {'bar':'wolf', 'baz':'rabbit'} 
map_level(data2, dct, level=0) 
print(data2) 
#      c1  c2 
# first second      
# wolf one  0.939040 -0.748100 
#  two -0.497006 -1.185966 
# rabbit one -0.368161 0.050339 
#  two -2.356879 -0.291206 
# foo one -0.556261 0.474297 
#  two  0.647973 0.755983 
# qux one -0.017722 1.364244 
#  two  1.007303 0.004337 
+0

0,13 vẫn đang được phát triển, tôi vẫn đang chạy 0.12.0. Có bất kỳ dấu hiệu nào về sự ổn định của 0.13x không? Tôi không thấy nhiều tài liệu về .index.set_levels. Trong ví dụ trên, mức cài đặt rất đơn giản vì chúng tôi chỉ có hai cấp. Từ điển có thể được chuyển để chỉ thay thế các giá trị trong một chỉ mục mà không cần chạm (hoặc phải chỉ định giá trị cho) các trục khác không? – tnknepp

+1

không hoạt động trong 0,16 nữa –

+1

Hoạt động tốt cho tôi trong 0.16.2 và 0.18.1 – joris

1

Phương pháp set_levels đã gây tên cột mới của tôi để được ra khỏi trật tự. Vì vậy, tôi tìm thấy một giải pháp khác nhau không phải là rất sạch sẽ, nhưng hoạt động tốt. Phương pháp này là print df.index (hoặc tương đương df.columns) và sau đó sao chép và dán đầu ra với các giá trị mong muốn đã thay đổi. Ví dụ:

print data.index 

MultiIndex (mức = [[ 'bar', 'baz', 'foo', 'qux'], [ 'one', 'hai']], nhãn = [[ 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]], tên = ['đầu tiên', 'giây'])

data.index = MultiIndex(levels=[['new_bar', 'new_baz', 'new_foo', 'new_qux'], 
           ['new_one', 'new_two']], 
         labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]], 
         names=['first', 'second']) 

Chúng tôi cũng có toàn quyền kiểm soát tên bằng cách chỉnh sửa nhãn.Ví dụ:

data.index = MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], 
           ['one', 'twooo', 'three', 'four', 
           'five', 'siz', 'seven', 'eit']], 
         labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 3, 4, 5, 6, 7]], 
         names=['first', 'second']) 

Lưu ý rằng trong ví dụ này, chúng tôi đã làm một cái gì đó giống như from pandas import MultiIndex hoặc from pandas import *.

+0

Tôi đang gặp vấn đề tương tự với set_levels đặt tên cột mới không đúng thứ tự. Tôi nghĩ rằng nó đang đặt tên cột mới dựa trên tham số "nhãn" trước đó của MultiIndex. Giải pháp tốt. – Eddy

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