2012-12-12 54 views
32

Tôi có khung dữ liệu pandas python, trong đó cột chứa tên tháng.Sắp xếp tùy chỉnh trong khung dữ liệu gấu trúc

Làm thế nào tôi có thể làm một tùy chỉnh loại sử dụng một cuốn từ điển, ví dụ:

custom_dict = {'March':0, 'April':1, 'Dec':3} 
+1

Một cột có chứa tên tháng có nghĩa là có cột chứa tên tháng (như câu trả lời của tôi) hoặc nhiều cột có tên cột làm tên tháng (như tên của eumiro)? –

Trả lời

48

Pandas 0,15 giới thiệu Categorical Series, cho phép một cách rõ ràng hơn để thực hiện việc này:

Đầu tiên, hãy tạo cột tháng một cách phân loại và chỉ định thứ tự sử dụng.

In [21]: df['m'] = pd.Categorical(df['m'], ["March", "April", "Dec"]) 

In [22]: df # looks the same! 
Out[22]: 
    a b  m 
0 1 2 March 
1 5 6 Dec 
2 3 4 April 

Bây giờ, khi bạn sắp xếp các cột tháng nó sẽ sắp xếp liên quan đến danh sách đó với:

In [23]: df.sort("m") 
Out[23]: 
    a b  m 
0 1 2 March 
2 3 4 April 
1 5 6 Dec 

Lưu ý: nếu một giá trị không nằm trong danh sách này sẽ được chuyển đổi sang NaN.


Một câu trả lời cũ cho những người quan tâm ...

Bạn có thể tạo một loạt trung gian, và set_index trên rằng:

df = pd.DataFrame([[1, 2, 'March'],[5, 6, 'Dec'],[3, 4, 'April']], columns=['a','b','m']) 
s = df['m'].apply(lambda x: {'March':0, 'April':1, 'Dec':3}[x]) 
s.sort() 

In [4]: df.set_index(s.index).sort() 
Out[4]: 
    a b  m 
0 1 2 March 
1 3 4 April 
2 5 6 Dec 

Như nhận xét, trong gấu trúc mới, Series có phương thức replace để làm điều này một cách trang nhã hơn:

s = df['m'].replace({'March':0, 'April':1, 'Dec':3}) 

Sự khác biệt nhỏ là điều này sẽ không tăng nếu có giá trị ngoài từ điển (nó sẽ chỉ giữ nguyên).

+0

's = df ['m']. Thay thế ({'March': 0, 'April': 1, 'Dec': 3})' hoạt động cho dòng 2 - chỉ vì lợi ích của bất kỳ ai học gấu trúc giống như tôi – kdauria

+0

@ kdauria vị trí tốt! (đã được một thời gian kể từ khi tôi đã viết này!) Thay thế chắc chắn lựa chọn tốt nhất, khác là sử dụng '.apply ({'March': 0, 'April': 1, 'Dec': 3} .get)' :) Trong 0.15 chúng ta sẽ có Categorical Series/columns, vì vậy cách tốt nhất là sử dụng nó và sau đó sắp xếp sẽ hoạt động. –

+0

@AndyHayden Tôi đã tự do thay thế dòng thứ hai bằng phương pháp 'thay thế'. Tôi hy vọng đó là Ok. –

2
import pandas as pd 
custom_dict = {'March':0,'April':1,'Dec':3} 

df = pd.DataFrame(...) # with columns April, March, Dec (probably alphabetically) 

df = pd.DataFrame(df, columns=sorted(custom_dict, key=custom_dict.get)) 

trả về một DataFrame với các cột Tháng Ba, Tháng Tư, Tháng Mười Hai

+0

Công việc này và dễ dàng hơn để viết shove trong bất kỳ mã hiện có. Cảm ơn bạn! – posdef

8

Một chút muộn cho trò chơi, nhưng đây là cách để tạo chức năng sắp xếp các chuỗi đối tượng DataFrame, DataFrame và multiindex DataFrame sử dụng các chức năng tùy ý.

Tôi sử dụng phương thức df.iloc[index], tham chiếu một hàng trong một Series/DataFrame theo vị trí (so với df.loc, tham chiếu theo giá trị). Sử dụng điều này, chúng tôi chỉ cần có một hàm trả về một loạt các đối số vị trí:

def sort_pd(key=None,reverse=False,cmp=None): 
    def sorter(series): 
     series_list = list(series) 
     return [series_list.index(i) 
      for i in sorted(series_list,key=key,reverse=reverse,cmp=cmp)] 
    return sorter 

Bạn có thể sử dụng tính năng này để tạo các chức năng sắp xếp tùy chỉnh. Này hoạt động trên các dataframe sử dụng trong câu trả lời Andy Hayden:

df = pd.DataFrame([ 
    [1, 2, 'March'], 
    [5, 6, 'Dec'], 
    [3, 4, 'April']], 
    columns=['a','b','m']) 

custom_dict = {'March':0, 'April':1, 'Dec':3} 
sort_by_custom_dict = sort_pd(key=custom_dict.get) 

In [6]: df.iloc[sort_by_custom_dict(df['m'])] 
Out[6]: 
    a b m 
0 1 2 March 
2 3 4 April 
1 5 6 Dec 

này cũng hoạt động trên DataFrames multiindex và các đối tượng Series:

months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] 

df = pd.DataFrame([ 
    ['New York','Mar',12714], 
    ['New York','Apr',89238], 
    ['Atlanta','Jan',8161], 
    ['Atlanta','Sep',5885], 
    ],columns=['location','month','sales']).set_index(['location','month']) 

sort_by_month = sort_pd(key=months.index) 

In [10]: df.iloc[sort_by_month(df.index.get_level_values('month'))] 
Out[10]: 
       sales 
location month 
Atlanta Jan 8161 
New York Mar 12714 
      Apr 89238 
Atlanta Sep 5885 

sort_by_last_digit = sort_pd(key=lambda x: x%10) 

In [12]: pd.Series(list(df['sales'])).iloc[sort_by_last_digit(df['sales'])] 
Out[12]: 
2 8161 
0 12714 
3 5885 
1 89238 

Đối với tôi đây cảm thấy sạch sẽ, nhưng nó sử dụng hoạt động trăn nặng nề hơn là dựa về các hoạt động gấu trúc được tối ưu hóa. Tôi đã không thực hiện bất kỳ thử nghiệm căng thẳng nhưng tôi tưởng tượng điều này có thể làm chậm trên DataFrames rất lớn. Không chắc chắn hiệu suất so sánh với việc thêm, sắp xếp, sau đó xóa cột. Bất kỳ lời khuyên nào về tăng tốc mã sẽ được đánh giá cao!

+0

Điều này có hoạt động để sắp xếp nhiều cột/chỉ mục không? – ConanG

+0

có, nhưng câu trả lời đã chọn là cách tốt hơn nhiều để thực hiện việc này. Nếu bạn có nhiều chỉ mục, chỉ cần sắp xếp chúng theo thứ tự sắp xếp bạn thích, sau đó sử dụng 'df.sort_index()' để sắp xếp tất cả các mức chỉ mục. – delgadom

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