Apakah kolom berisi nama bulan berarti ada kolom yang berisi nama bulan (sebagai jawaban saya), atau banyak kolom dengan nama kolom sebagai nama bulan (sebagai eumiro's)?
Andy Hayden
1
Jawaban yang diterima sudah usang, dan juga secara teknis salah, karena pd.Categoricaltidak menafsirkan kategori seperti yang diurutkan secara default. Lihat jawaban ini .
cs95
Jawaban:
149
Pandas 0.15 memperkenalkan Categorical Series , yang memungkinkan cara yang lebih jelas untuk melakukan ini:
Pertama buat kolom bulan menjadi kategorikal dan tentukan urutan yang akan digunakan.
In [21]: df['m'] = pd.Categorical(df['m'], ["March", "April", "Dec"])
In [22]: df # looks the same!
Out[22]:
a b m
012 March
156 Dec
234 April
Sekarang, ketika Anda mengurutkan kolom bulan itu akan mengurutkan sehubungan dengan daftar itu:
In [23]: df.sort_values("m")
Out[23]:
a b m
012 March
234 April
156 Dec
Catatan: jika suatu nilai tidak ada dalam daftar, itu akan dikonversi ke NaN.
Jawaban yang lebih tua bagi mereka yang tertarik ...
Anda bisa membuat seri perantara, dan set_indexdi atasnya:
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
012 March
134 April
256 Dec
Seperti yang dikomentari, di panda yang lebih baru, Series memiliki replacemetode untuk melakukannya dengan lebih elegan:
s = df['m'].replace({'March':0, 'April':1, 'Dec':3})
Perbedaan kecilnya adalah bahwa ini tidak akan meningkat jika ada nilai di luar kamus (itu hanya akan tetap sama).
s = df['m'].replace({'March':0, 'April':1, 'Dec':3})berfungsi untuk baris 2 juga - hanya untuk siapa saja yang mempelajari panda seperti saya
kdauria
@kdauria tempat yang bagus! (sudah lama sejak saya menulis ini!) ganti pilihan terbaik yang pasti, yang lain adalah menggunakan .apply({'March':0, 'April':1, 'Dec':3}.get):) Dalam 0.15 kita akan memiliki Seri / kolom Kategorikal, jadi cara terbaik adalah menggunakan itu dan kemudian mengurutkan hanya akan bekerja.
Andy Hayden
@AndyHayden Saya telah mengambil kebebasan untuk mengganti baris kedua dengan metode 'ganti'. Saya harap itu baik-baik saja.
Faheem Mitha
Edit @AndyHayden ditolak, tetapi menurut saya ini adalah perubahan yang wajar.
Faheem Mitha
7
Pastikan Anda menggunakan df.sort_values("m")panda yang lebih baru (bukan df.sort("m")), jika tidak Anda akan mendapatkan AttributeError: 'DataFrame' object has no attribute 'sort';)
brainstorming
21
panda> = 1.1
Anda akan segera dapat menggunakan sort_valuesdengan keyargumen:
pd.__version__
# '1.1.0.dev0+2004.g8d10bfb6f'
custom_dict = {'March': 0, 'April': 1, 'Dec': 3}
df
a b m
012 March
156 Dec
234 April
df.sort_values(by=['m'], key=lambda x: x.map(custom_dict))
a b m
012 March
234 April
156 Dec
The keyArgumen mengambil sebagai masukan Series dan kembali Seri. Seri ini diurutkan secara internal dan indeks yang diurutkan digunakan untuk menyusun ulang input DataFrame. Jika ada beberapa kolom untuk diurutkan, fungsi kunci akan diterapkan ke setiap kolom secara bergantian. Lihat Menyortir dengan kunci .
panda <= 1.0.X
Satu metode sederhana adalah menggunakan output Series.mapdan Series.argsortmengindeks ke dalam dfpenggunaan DataFrame.iloc(karena argsort menghasilkan posisi integer yang diurutkan); karena Anda memiliki kamus; ini menjadi mudah.
df.iloc[df['m'].map(custom_dict).argsort()]
a b m
012 March
234 April
156 Dec
Jika Anda perlu mengurutkan dalam urutan menurun , balikkan pemetaan.
df.iloc[(-df['m'].map(custom_dict)).argsort()]
a b m
156 Dec
234 April
012 March
Perhatikan bahwa ini hanya berfungsi pada item numerik. Jika tidak, Anda perlu mengatasinya dengan menggunakan sort_values, dan mengakses indeks:
df.loc[df['m'].map(custom_dict).sort_values(ascending=False).index]
a b m
156 Dec
234 April
012 March
Lebih banyak opsi tersedia dengan astype(ini tidak digunakan lagi sekarang), atau pd.Categorical, tetapi Anda perlu menentukannya ordered=Trueagar berfungsi dengan benar .
Anda sudah menekankannya, tetapi saya ingin mengulangi jika ada orang lain yang membaca sekilas dan melewatkannya: Pandas Categorical disetel ordered=Nonesecara default. Jika tidak disetel, urutannya akan salah, atau rusak di V23. Fungsi Max khususnya memberikan TypeError (Categorical tidak dipesan untuk operasi max).
Dave Liu
17
Memperbarui
gunakan jawaban yang dipilih ! Ini lebih baru dari posting ini dan bukan hanya cara resmi untuk memelihara data yang dipesan di panda, itu lebih baik dalam segala hal, termasuk fitur / kinerja, dll. Jangan gunakan metode hacky yang saya jelaskan di bawah ini.
Saya hanya menulis pembaruan ini karena orang-orang terus memberi suara positif pada jawaban saya, tetapi ini jelas lebih buruk daripada yang diterima :)
Posting asli
Agak terlambat untuk permainan, tapi berikut adalah cara untuk membuat fungsi yang mengurutkan pandas Series, DataFrame, dan multiindex objek DataFrame menggunakan fungsi arbitrer.
Saya menggunakan df.iloc[index]metode ini, yang mereferensikan baris dalam Seri / DataFrame berdasarkan posisi (dibandingkan df.loc, yang mereferensikan berdasarkan nilai). Menggunakan ini, kita hanya perlu memiliki sebuah fungsi yang mengembalikan serangkaian argumen posisi:
defsort_pd(key=None,reverse=False,cmp=None):defsorter(series):
series_list = list(series)
return [series_list.index(i)
for i insorted(series_list,key=key,reverse=reverse,cmp=cmp)]
return sorter
Anda dapat menggunakan ini untuk membuat fungsi pengurutan kustom. Ini bekerja pada kerangka data yang digunakan dalam jawaban 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
012 March
234 April
156 Dec
Ini juga berfungsi pada objek DataFrames dan Series multiindex:
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]:
2816101271435885189238
Bagi saya ini terasa bersih, tetapi menggunakan operasi python daripada mengandalkan operasi panda yang dioptimalkan. Saya belum melakukan pengujian stres tetapi saya membayangkan ini bisa menjadi lambat pada DataFrames yang sangat besar. Tidak yakin bagaimana kinerja dibandingkan dengan menambahkan, menyortir, lalu menghapus kolom. Setiap tip untuk mempercepat kode akan sangat kami hargai!
Apakah ini akan berfungsi untuk menyortir banyak kolom / indeks?
ConanG
ya, tetapi jawaban yang dipilih adalah cara yang jauh lebih baik untuk melakukan ini. Jika Anda memiliki beberapa indeks, cukup susun menurut urutan yang Anda inginkan, lalu gunakan df.sort_index()untuk mengurutkan semua tingkat indeks.
Michael Delgado
9
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))
mengembalikan DataFrame dengan kolom Maret, April, Desember
pd.Categorical
tidak menafsirkan kategori seperti yang diurutkan secara default. Lihat jawaban ini .Jawaban:
Pandas 0.15 memperkenalkan Categorical Series , yang memungkinkan cara yang lebih jelas untuk melakukan ini:
Pertama buat kolom bulan menjadi kategorikal dan tentukan urutan yang akan digunakan.
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
Sekarang, ketika Anda mengurutkan kolom bulan itu akan mengurutkan sehubungan dengan daftar itu:
In [23]: df.sort_values("m") Out[23]: a b m 0 1 2 March 2 3 4 April 1 5 6 Dec
Catatan: jika suatu nilai tidak ada dalam daftar, itu akan dikonversi ke NaN.
Jawaban yang lebih tua bagi mereka yang tertarik ...
Anda bisa membuat seri perantara, dan
set_index
di atasnya: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
Seperti yang dikomentari, di panda yang lebih baru, Series memiliki
replace
metode untuk melakukannya dengan lebih elegan:s = df['m'].replace({'March':0, 'April':1, 'Dec':3})
Perbedaan kecilnya adalah bahwa ini tidak akan meningkat jika ada nilai di luar kamus (itu hanya akan tetap sama).
sumber
s = df['m'].replace({'March':0, 'April':1, 'Dec':3})
berfungsi untuk baris 2 juga - hanya untuk siapa saja yang mempelajari panda seperti saya.apply({'March':0, 'April':1, 'Dec':3}.get)
:) Dalam 0.15 kita akan memiliki Seri / kolom Kategorikal, jadi cara terbaik adalah menggunakan itu dan kemudian mengurutkan hanya akan bekerja.df.sort_values("m")
panda yang lebih baru (bukandf.sort("m")
), jika tidak Anda akan mendapatkanAttributeError: 'DataFrame' object has no attribute 'sort'
;)panda> = 1.1
Anda akan segera dapat menggunakan
sort_values
dengankey
argumen: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
The
key
Argumen mengambil sebagai masukan Series dan kembali Seri. Seri ini diurutkan secara internal dan indeks yang diurutkan digunakan untuk menyusun ulang input DataFrame. Jika ada beberapa kolom untuk diurutkan, fungsi kunci akan diterapkan ke setiap kolom secara bergantian. Lihat Menyortir dengan kunci .panda <= 1.0.X
Satu metode sederhana adalah menggunakan output
Series.map
danSeries.argsort
mengindeks ke dalamdf
penggunaanDataFrame.iloc
(karena argsort menghasilkan posisi integer yang diurutkan); karena Anda memiliki kamus; ini menjadi mudah.df.iloc[df['m'].map(custom_dict).argsort()] a b m 0 1 2 March 2 3 4 April 1 5 6 Dec
Jika Anda perlu mengurutkan dalam urutan menurun , balikkan pemetaan.
df.iloc[(-df['m'].map(custom_dict)).argsort()] a b m 1 5 6 Dec 2 3 4 April 0 1 2 March
Perhatikan bahwa ini hanya berfungsi pada item numerik. Jika tidak, Anda perlu mengatasinya dengan menggunakan
sort_values
, dan mengakses indeks: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
Lebih banyak opsi tersedia dengan
astype
(ini tidak digunakan lagi sekarang), ataupd.Categorical
, tetapi Anda perlu menentukannyaordered=True
agar berfungsi dengan benar .# 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)
Sekarang,
sort_values
panggilan sederhana akan berhasil:df.sort_values('m') a b m 0 1 2 March 2 3 4 April 1 5 6 Dec
Urutan kategoris juga akan diberlakukan saat
groupby
mengurutkan output.sumber
ordered=None
secara default. Jika tidak disetel, urutannya akan salah, atau rusak di V23. Fungsi Max khususnya memberikan TypeError (Categorical tidak dipesan untuk operasi max).Memperbarui
gunakan jawaban yang dipilih ! Ini lebih baru dari posting ini dan bukan hanya cara resmi untuk memelihara data yang dipesan di panda, itu lebih baik dalam segala hal, termasuk fitur / kinerja, dll. Jangan gunakan metode hacky yang saya jelaskan di bawah ini.
Saya hanya menulis pembaruan ini karena orang-orang terus memberi suara positif pada jawaban saya, tetapi ini jelas lebih buruk daripada yang diterima :)
Posting asli
Agak terlambat untuk permainan, tapi berikut adalah cara untuk membuat fungsi yang mengurutkan pandas Series, DataFrame, dan multiindex objek DataFrame menggunakan fungsi arbitrer.
Saya menggunakan
df.iloc[index]
metode ini, yang mereferensikan baris dalam Seri / DataFrame berdasarkan posisi (dibandingkandf.loc
, yang mereferensikan berdasarkan nilai). Menggunakan ini, kita hanya perlu memiliki sebuah fungsi yang mengembalikan serangkaian argumen posisi: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
Anda dapat menggunakan ini untuk membuat fungsi pengurutan kustom. Ini bekerja pada kerangka data yang digunakan dalam jawaban 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
Ini juga berfungsi pada objek DataFrames dan Series multiindex:
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
Bagi saya ini terasa bersih, tetapi menggunakan operasi python daripada mengandalkan operasi panda yang dioptimalkan. Saya belum melakukan pengujian stres tetapi saya membayangkan ini bisa menjadi lambat pada DataFrames yang sangat besar. Tidak yakin bagaimana kinerja dibandingkan dengan menambahkan, menyortir, lalu menghapus kolom. Setiap tip untuk mempercepat kode akan sangat kami hargai!
sumber
df.sort_index()
untuk mengurutkan semua tingkat indeks.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))
mengembalikan DataFrame dengan kolom Maret, April, Desember
sumber