Saya memiliki bingkai data dengan indeks hierarki di sumbu 1 (kolom) (dari groupby.agg
operasi):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf
sum sum sum sum amax amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Saya ingin meratakannya, sehingga terlihat seperti ini (nama tidak kritis - saya bisa mengganti nama):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf_amax tmpf_amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Bagaimana saya melakukan ini? (Saya sudah mencoba banyak, tetapi tidak berhasil.)
Per saran, di sini adalah kepala dalam bentuk dikt
{('USAF', ''): {0: '702730',
1: '702730',
2: '702730',
3: '702730',
4: '702730'},
('WBAN', ''): {0: '26451', 1: '26451', 2: '26451', 3: '26451', 4: '26451'},
('day', ''): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
('month', ''): {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
('s_CD', 'sum'): {0: 12.0, 1: 13.0, 2: 2.0, 3: 12.0, 4: 10.0},
('s_CL', 'sum'): {0: 0.0, 1: 0.0, 2: 10.0, 3: 0.0, 4: 0.0},
('s_CNT', 'sum'): {0: 13.0, 1: 13.0, 2: 13.0, 3: 13.0, 4: 13.0},
('s_PC', 'sum'): {0: 1.0, 1: 0.0, 2: 1.0, 3: 1.0, 4: 3.0},
('tempf', 'amax'): {0: 30.920000000000002,
1: 32.0,
2: 23.0,
3: 10.039999999999999,
4: 19.939999999999998},
('tempf', 'amin'): {0: 24.98,
1: 24.98,
2: 6.9799999999999969,
3: 3.9199999999999982,
4: 10.940000000000001},
('year', ''): {0: 1993, 1: 1993, 2: 1993, 3: 1993, 4: 1993}}
df[:5].to_dict()
sebagai contoh untuk dibaca orang lain dalam dataset Anda?pandas
pelacak masalah untuk menerapkan metode khusus untuk ini.dat.columns = dat.columns.to_flat_index()
. Fungsi panda bawaan.Jawaban:
Saya pikir cara termudah untuk melakukan ini adalah dengan mengatur kolom ke tingkat atas:
Catatan: jika level to memiliki nama Anda juga dapat mengaksesnya dengan ini, daripada 0.
.
Jika Anda ingin menggabungkan /
join
MultiIndex Anda menjadi satu Indeks (dengan asumsi Anda hanya memiliki entri string di kolom Anda ) Anda bisa:Catatan: kita harus
strip
spasi ketika ketika tidak ada indeks kedua.sumber
['_'.join(col).rstrip('_') for col in df.columns.values]
sum s_CD
bukan yangs_CD sum
bisa dilakukandf.columns = ['_'.join(col).rstrip('_') for col in [c[::-1] for c in df.columns.values]]
.sumber
pd.DataFrame(df.to_records(), columns=df.index.names + list(df.columns))
pd.DataFrame(df_volume.to_records(), index=df_volume.index).drop('index', axis=1)
Semua jawaban saat ini di utas ini pasti sedikit bertanggal. Pada
pandas
versi 0.24.0,.to_flat_index()
lakukan apa yang Anda butuhkan.Dari dokumentasi panda sendiri :
Contoh sederhana dari dokumentasinya:
Menerapkan
to_flat_index()
:Menggunakannya untuk mengganti
pandas
kolom yang adaContoh cara Anda menggunakannya
dat
, yaitu DataFrame denganMultiIndex
kolom:sumber
Jawaban Andy Hayden tentu saja merupakan cara termudah - jika Anda ingin menghindari label kolom duplikat Anda perlu sedikit mengubah
sumber
sumber
Dan jika Anda ingin mempertahankan informasi agregasi dari tingkat kedua multiindex Anda dapat mencoba ini:
sumber
new_cols
tidak ditentukan.Cara paling pythonic untuk melakukan ini menggunakan
map
fungsi.Output
print(df.columns)
:Perbarui menggunakan Python 3.6+ dengan f string:
Keluaran:
sumber
Solusi termudah dan paling intuitif bagi saya adalah menggabungkan nama kolom menggunakan get_level_values . Ini mencegah nama kolom duplikat ketika Anda melakukan lebih dari satu agregasi pada kolom yang sama:
Jika Anda ingin pemisah antar kolom, Anda bisa melakukan ini. Ini akan mengembalikan hal yang sama dengan komentar Seiji Armstrong pada jawaban yang diterima yang hanya mencakup garis bawah untuk kolom dengan nilai di kedua level indeks:
Saya tahu ini melakukan hal yang sama dengan jawaban hebat Andy Hayden di atas, tapi saya pikir ini sedikit lebih intuitif dengan cara ini dan lebih mudah diingat (jadi saya tidak harus terus merujuk ke utas ini), terutama untuk pengguna panda pemula .
Metode ini juga lebih dapat dikembangkan jika Anda memiliki 3 level kolom.
sumber
Setelah membaca semua jawaban, saya datang dengan ini:
Pemakaian:
Diberi bingkai data:
Metode agregasi tunggal : variabel yang dihasilkan dinamai sama dengan sumber :
df.groupby(by="grouper",
as_index = Salah)
atau.agg(...)
.reset_index ()Variabel sumber tunggal, banyak agregasi : variabel yang dihasilkan dinamai menurut statistik :
a = df.groupby(..).agg(..); a.columns = a.columns.droplevel(0); a.reset_index()
.Beberapa variabel, banyak agregasi : variabel yang dihasilkan bernama (varname) _ (statname) :
a.columns = ["_".join(filter(None, map(str, levels))) for levels in a.columns.values]
bawah tenda (karena iniagg()
menghasilkanMultiIndex
kolom-kolom).my_flatten_cols
helper, mungkin lebih mudah untuk mengetikkan solusi yang disarankan oleh @Seigi :a.columns = ["_".join(t).rstrip("_") for t in a.columns.values]
, yang bekerja sama dalam hal ini (tapi gagal jika Anda memiliki label numerik pada kolom)a.columns = ["_".join(tuple(map(str, t))).rstrip("_") for t in a.columns.values]
), tapi saya tidak mengerti mengapatuple()
panggilan itu diperlukan, dan saya percayarstrip()
hanya diperlukan jika beberapa kolom memiliki deskriptor seperti("colname", "")
( yang dapat terjadi jika Andareset_index()
sebelum mencoba memperbaiki.columns
)Anda ingin nama variabel yang dihasilkan secara manual: (ini ditinggalkan karena panda 0.20.0 dengan tidak ada alternatif yang memadai sebagai 0,23 )
res.columns = ['A_sum', 'B_sum', 'count']
atau memasukkan.join()
banyakgroupby
pernyataan.Kasus yang ditangani oleh fungsi pembantu
map(str, ..)
filter(None, ..)
columns.values
mengembalikan nama (str
, bukan tupel).agg()
Anda mungkin perlu menjaga label terbawah untuk kolom atau menggabungkan beberapa labelreset_index()
dapat bekerja dengan kolom kelompok-per-cara secara teratur, jadi ia melakukannya secara defaultsumber
tuple()
diperlukan, Anda mungkin ingin mengomentari posting jxstanford. Jika tidak, mungkin akan membantu untuk memeriksa.columns.values
dalam contoh yang diberikan:[('val1', 'min'), (2, 'sum'), (2, 'size')]
. 1)for t in a.columns.values
loop di atas kolom, untuk kolom keduat == (2, 'sum')
; 2)map(str, t)
berlakustr()
untuk setiap "level", menghasilkan('2', 'sum')
; 3)"_".join(('2','sum'))
menghasilkan "2_sum",Solusi umum yang menangani beberapa level dan tipe campuran:
sumber
df.columns = ['_'.join(tuple(map(str, t))).rstrip('_') for t in df.columns.values]
Agak terlambat mungkin, tetapi jika Anda tidak khawatir tentang duplikat nama kolom:
sumber
(year, )
dan(tempf, amax)
Jika Anda ingin memiliki pemisah dalam nama antar level, fungsi ini berfungsi dengan baik.
sumber
df.columns = ["_".join(filter(None, c)) for c in df.columns]
Mengikuti @jxstanford dan @ tvt173, saya menulis fungsi cepat yang seharusnya melakukan trik, terlepas dari nama kolom string / int:
sumber
Anda juga bisa melakukan seperti di bawah ini. Pertimbangkan
df
untuk menjadi kerangka data Anda dan anggap indeks dua tingkat (seperti halnya dalam contoh Anda)sumber
Saya akan berbagi cara langsung yang bekerja untuk saya.
sumber
Untuk meratakan MultiIndex di dalam rangkaian metode DataFrame lainnya, tentukan fungsi seperti ini:
Kemudian gunakan
pipe
metode untuk menerapkan fungsi ini dalam rantai metode DataFrame, setelahgroupby
danagg
tetapi sebelum metode lain dalam rantai:sumber
Rutinitas sederhana lain.
sumber