Tôi có khung dữ liệu pandas python, trong đó một cột chứa tên tháng.
Làm cách nào để thực hiện sắp xếp tùy chỉnh bằng từ điển, ví dụ:
custom_dict = {'March':0, 'April':1, 'Dec':3}
Tôi có khung dữ liệu pandas python, trong đó một cột chứa tên tháng.
Làm cách nào để thực hiện sắp xếp tùy chỉnh bằng từ điển, ví dụ:
custom_dict = {'March':0, 'April':1, 'Dec':3}
pd.Categorical
không giải thích các danh mục theo thứ tự theo mặc định. Xem câu trả lời này .
Câu trả lời:
Pandas 0.15 đã giới thiệu chuỗi Categorical , cho phép một cách rõ ràng hơn nhiều để làm điều này:
Đầu tiên, hãy đặt cột tháng thành một 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ột tháng, nó sẽ sắp xếp theo danh sách đó:
In [23]: df.sort_values("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 có trong danh sách, nó sẽ được chuyển đổi thành NaN.
Một câu trả lời cũ hơn cho những người quan tâm ...
Bạn có thể tạo một chuỗi trung gian và set_index
trên đó:
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_values()
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, ở những con gấu trúc mới hơn, Series có một replace
phương pháp để làm điều này một cách thanh lịch 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 lên nếu có một giá trị bên ngoài từ điển (nó sẽ giữ nguyên).
s = df['m'].replace({'March':0, 'April':1, 'Dec':3})
làm việc cho dòng 2 cũng - chỉ vì lợi ích của bất cứ ai học gấu trúc như tôi
.apply({'March':0, 'April':1, 'Dec':3}.get)
Thay thế chắc chắn là lựa chọn tốt nhất, một lựa chọn khác là sử dụng :) Trong 0.15, chúng ta sẽ có Chuỗi / cột Categorical, vì vậy cách tốt nhất sẽ là sử dụng tùy chọn đó và sau đó sắp xếp sẽ hoạt động.
df.sort_values("m")
trong gấu trúc mới hơn (thay vì df.sort("m")
), nếu không bạn sẽ nhận được một AttributeError: 'DataFrame' object has no attribute 'sort'
;)
Bạn sẽ sớm có thể sử dụng sort_values
với key
đối số:
pd.__version__
# '1.1.0.dev0+2004.g8d10bfb6f'
custom_dict = {'March': 0, 'April': 1, 'Dec': 3}
df
a b m
0 1 2 March
1 5 6 Dec
2 3 4 April
df.sort_values(by=['m'], key=lambda x: x.map(custom_dict))
a b m
0 1 2 March
2 3 4 April
1 5 6 Dec
Đối key
số nhận đầu vào là một Chuỗi và trả về một Chuỗi. Chuỗi này được sắp xếp nội bộ và các chỉ số được sắp xếp được sử dụng để sắp xếp lại DataFrame đầu vào. Nếu có nhiều cột để sắp xếp, chức năng chính sẽ được áp dụng lần lượt cho từng cột. Xem Sắp xếp bằng phím .
Một phương pháp đơn giản là sử dụng đầu ra Series.map
và Series.argsort
lập chỉ mục để df
sử dụng DataFrame.iloc
(vì argsort tạo ra các vị trí số nguyên được sắp xếp); vì bạn có từ điển; điều này trở nên dễ dàng.
df.iloc[df['m'].map(custom_dict).argsort()]
a b m
0 1 2 March
2 3 4 April
1 5 6 Dec
Nếu bạn cần sắp xếp theo thứ tự giảm dần , hãy đảo ngược ánh xạ.
df.iloc[(-df['m'].map(custom_dict)).argsort()]
a b m
1 5 6 Dec
2 3 4 April
0 1 2 March
Lưu ý rằng điều này chỉ hoạt động trên các mục số. Nếu không, bạn sẽ cần phải giải quyết vấn đề này bằng cách sử dụng sort_values
và truy cập chỉ mục:
df.loc[df['m'].map(custom_dict).sort_values(ascending=False).index]
a b m
1 5 6 Dec
2 3 4 April
0 1 2 March
Có nhiều tùy chọn hơn với astype
(tính năng này hiện không được dùng nữa), hoặc pd.Categorical
, nhưng bạn cần chỉ định ordered=True
để nó hoạt động chính xác .
# Older version,
# df['m'].astype('category',
# categories=sorted(custom_dict, key=custom_dict.get),
# ordered=True)
df['m'] = pd.Categorical(df['m'],
categories=sorted(custom_dict, key=custom_dict.get),
ordered=True)
Bây giờ, một sort_values
cuộc gọi đơn giản sẽ thực hiện thủ thuật:
df.sort_values('m')
a b m
0 1 2 March
2 3 4 April
1 5 6 Dec
Thứ tự phân loại cũng sẽ được thực hiện khi groupby
sắp xếp đầu ra.
ordered=None
theo mặc định. Nếu không được đặt, thứ tự sẽ bị sai hoặc bị hỏng trên V23. Đặc biệt, hàm Max đưa ra một TypeError (Categorical không được sắp xếp cho hoạt động max).
Trò chơi hơi muộn, nhưng đây là cách để tạo một hàm sắp xếp các đối tượng Dòng gấu trúc, DataFrame và Multiindex DataFrame bằng các hàm tùy ý.
Tôi sử dụng df.iloc[index]
phương thức này, tham chiếu một hàng trong 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 ta 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 điều này để tạo các chức năng sắp xếp tùy chỉnh. Điều này hoạt động trên khung dữ liệu được sử dụng trong câu trả lời của 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
Điều này cũng hoạt động trên các đối tượng DataFrames và Series đa chỉ mục:
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, điều này cảm thấy sạch sẽ, nhưng nó sử dụng nhiều hoạt động của python thay vì dựa vào các hoạt động của gấu trúc được tối ưu hóa. Tôi chưa thực hiện bất kỳ thử nghiệm căng thẳng nào nhưng tôi tưởng tượng điều này có thể bị chậm trên các DataFrame rất lớn. Không chắc chắn hiệu suất như thế nào so với thêm, sắp xếp, sau đó xóa một cột. Bất kỳ mẹo nào về tăng tốc mã sẽ được đánh giá cao!
df.sort_index()
để sắp xếp tất cả các cấp chỉ mục.
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ề DataFrame với các cột Tháng 3, Tháng 4, Tháng 12