Menambahkan meta-informasi / metadata ke pandas DataFrame

90

Apakah mungkin untuk menambahkan beberapa meta-informasi / metadata ke DataFrame pandas?

Misalnya nama instrumen yang digunakan untuk mengukur data, instrumen yang bertanggung jawab, dll.

Salah satu solusinya adalah membuat kolom dengan informasi tersebut, tetapi tampaknya sia-sia untuk menyimpan satu informasi di setiap baris!

P3trus
sumber
Harap perhatikan jawaban @ryanjdillon (saat ini terkubur di dekat bagian bawah) yang menyebutkan atribut eksperimental yang diperbarui 'attrs' yang sepertinya permulaan, mungkin
JohnE

Jawaban:

85

Tentu, seperti kebanyakan objek Python, Anda dapat melampirkan atribut baru ke pandas.DataFrame:

import pandas as pd
df = pd.DataFrame([])
df.instrument_name = 'Binky'

Catatan, bagaimanapun, bahwa sementara Anda dapat melampirkan atribut untuk DataFrame, operasi dilakukan pada DataFrame (seperti groupby, pivot, joinatau lochanya beberapa nama) dapat kembali DataFrame baru tanpa metadata terpasang. Panda belum memiliki metode yang kuat untuk menyebarkan metadata yang dilampirkan ke DataFrames .

Menjaga metadata dalam file dimungkinkan. Anda dapat menemukan contoh cara menyimpan metadata dalam file HDF5 di sini .

unutbu
sumber
5
1 untuk Anda pilihan nama instrumen! Apakah Anda memiliki pengalaman mencoba membuang atribut tambahan ini ke HDFStore?
Dan Allan
4
@DanAllan: Jika store = pd.HDFStore(...), maka atribut dapat disimpan dengan store.root._v_attrs.key = value.
unutbu
3
Kepada siapa pun yang mungkin menggunakan ini: dokumen telah menambahkan bagian tentang ini. pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore
Dan Allan
4
Dalam pandas 0.23.1, membuat atribut baru dengan menetapkan kamus, daftar, atau tupel akan memberikan peringatan (yaitu df = pd.DataFrame(); df.meta = {}menghasilkan UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access). (Tidak ada peringatan yang diberikan jika atribut telah dibuat seperti di df = pd.DataFrame(); df.meta = ''; df.meta = {}).
teichert
13

Saya sendiri mengalami masalah ini. Mulai pandas 0.13, DataFrames memiliki atribut _metadata yang tetap ada melalui fungsi yang mengembalikan DataFrames baru. Juga tampaknya bertahan serialisasi dengan baik (saya hanya mencoba json, tapi saya membayangkan hdf tercakup juga).

kebodohan
sumber
16
_metadatabukan bagian dari API publik, jadi saya sangat menyarankan agar Anda tidak mengandalkan fungsi ini.
shoyer
@ Stephan, bisakah Anda menjelaskannya? Mengapa penting untuk menjadi bagian dari API publik? Apakah pernyataan Anda juga benar untuk versi 0.15?
TomCho
1
@TomCho ya, jawaban itu masih berlaku sampai sekarang. Anda dapat melihat xray ( github.com/xray/xray ) untuk satu contoh alternatif dari larik berlabel yang mendukung metadata, terutama jika Anda memiliki data multi-dimensi ( .attrsmerupakan bagian dari xray API)
shoyer
17
_metadatasebenarnya adalah atribut kelas, bukan atribut instance. Jadi DataFrameinstance baru diturunkan dari yang sebelumnya, selama modul tetap dimuat. Jangan gunakan _metadatauntuk apapun. 1 untuk xarray!
j08lue
1
_metadata - fitur tidak didukung yang menyelamatkan hari saya! Terima kasih.
joctee
12

Tidak juga. Meskipun Anda bisa menambahkan atribut yang berisi metadata ke kelas DataFrame seperti yang @unutbu sebutkan, banyak metode DataFrame mengembalikan DataFrame baru, sehingga data meta Anda akan hilang. Jika Anda perlu memanipulasi dataframe Anda, maka opsi terbaik adalah menggabungkan metadata dan DataFrame Anda di kelas lain. Lihat diskusi ini di GitHub: https://github.com/pydata/pandas/issues/2485

Saat ini ada permintaan tarik terbuka untuk menambahkan objek MetaDataFrame, yang akan mendukung metadata dengan lebih baik.

Matti John
sumber
11

Mulai dari panda 1.0, mungkin sebelumnya, sekarang ada Dataframe.attrsproperti. Ini eksperimental, tetapi ini mungkin yang Anda inginkan di masa mendatang. Sebagai contoh:

import pandas as pd
df = pd.DataFrame([])
df.attrs['instrument_name'] = 'Binky'

Temukan di dokumen di sini .

Mencoba ini dengan to_parquetdan kemudian from_parquet, tampaknya tidak bertahan, jadi pastikan Anda memeriksanya dengan kasus penggunaan Anda.

ryanjdillon.dll
sumber
Ini menarik dan tampaknya tetap ada untuk copy / loc / iloc, tetapi tidak untuk groupby.
JohnE
Hanya saran, tetapi mungkin menunjukkan contoh bagaimana cara menggunakannya? Dokumentasi pada dasarnya tidak ada apa-apanya, tetapi hanya dari bermain-main dengannya saya dapat melihat bahwa itu diinisialisasi sebagai kamus kosong dan tampaknya diatur sehingga harus menjadi kamus meskipun tentu saja seseorang dapat menyusun daftar di dalamnya, sebagai contoh.
JohnE
1
Anda mungkin menemukan diskusi Stackoverflow ini berguna karena ini menunjukkan cara menambahkan metadata khusus ke file parket jika diperlukan
rdmolony
1
@rdolony Itu bagus. Saya pikir menggunakan a dataclassuntuk metadata dan kemudian subclassing DataFramememiliki metode melakukan load / dumping seperti pada posting yang Anda bagikan bisa menjadi solusi yang bagus.
ryanjdillon
1
Ini bagus. Berbeda dengan jawaban yang diterima, ini mempertahankan atribut setelah menyimpan dan memuat dari acar!
CGFoX
8

Jawaban teratas dari melampirkan atribut arbitrer ke objek DataFrame adalah baik, tetapi jika Anda menggunakan kamus, daftar, atau tuple, ini akan mengeluarkan kesalahan "Pandas tidak mengizinkan kolom dibuat melalui nama atribut baru". Solusi berikut berfungsi untuk menyimpan atribut arbitrer.

from types import SimpleNamespace
df = pd.DataFrame()
df.meta = SimpleNamespace()
df.meta.foo = [1,2,3]
bscan
sumber
Selain itu, jika Anda ingin ini tetap ada di seluruh salinan kerangka data Anda, Anda perlu melakukannya pd.DataFrame._metadata += ["meta"]. Perhatikan bahwa bagian ini adalah atribut Pandas, bukan atribut dataframe spesifik Anda
bscan
Pendekatan ini tidak akan berfungsi lagi karena df.metamemicu peringatan bahwa Pandas tidak mengizinkan kolom baru dibuat dengan cara ini.
anishtain4
@ anishtain4, saya baru saja mengujinya dengan Pandas 25.1 (dirilis ~ 2 minggu yang lalu) dan kode ini masih berfungsi untuk saya. Peringatan itu tidak dipicu karena df.metamerupakan SimpleNamespace. Panda tidak akan mencoba dan membangun kolom darinya.
bscan
6

Seperti yang disebutkan dalam jawaban dan komentar lain, _metadataini bukan bagian dari API publik, jadi jelas bukan ide yang baik untuk menggunakannya dalam lingkungan produksi. Tetapi Anda mungkin masih ingin menggunakannya dalam pembuatan prototipe penelitian dan menggantinya jika berhenti berfungsi. Dan sekarang ini bekerja dengan groupby/ apply, yang sangat membantu. Ini adalah contoh (yang tidak dapat saya temukan di jawaban lain):

df = pd.DataFrame([1, 2, 2, 3, 3], columns=['val']) 
df.my_attribute = "my_value"
df._metadata.append('my_attribute')
df.groupby('val').apply(lambda group: group.my_attribute)

Keluaran:

val
1    my_value
2    my_value
3    my_value
dtype: object
Dennis Golomazov
sumber
4

Sangat terlambat untuk ini, saya pikir ini mungkin berguna jika Anda memerlukan metadata untuk bertahan selama I / O. Ada paket yang relatif baru bernama h5io yang telah saya gunakan untuk mencapai ini.

Seharusnya Anda dapat melakukan baca / tulis cepat dari HDF5 untuk beberapa format umum, salah satunya adalah kerangka data. Jadi Anda bisa, misalnya, meletakkan kerangka data di kamus dan memasukkan metadata sebagai bidang di kamus. Misalnya:

save_dict = dict(data=my_df, name='chris', record_date='1/1/2016')
h5io.write_hdf5('path/to/file.hdf5', save_dict)
in_data = h5io.read_hdf5('path/to/file.hdf5')
df = in_data['data']
name = in_data['name']
etc...

Pilihan lain adalah melihat ke dalam proyek seperti xray , yang lebih kompleks dalam beberapa hal, tapi menurut saya itu memungkinkan Anda menggunakan metadata dan cukup mudah untuk diubah menjadi DataFrame.

choldgraf.dll
sumber
4

Seperti yang disebutkan oleh @choldgraf, saya telah menemukan xarray sebagai alat yang sangat baik untuk melampirkan metadata ketika membandingkan data dan memplot hasil antara beberapa kerangka data.

Dalam pekerjaan saya, kami sering membandingkan hasil dari beberapa revisi firmware dan skenario pengujian yang berbeda, menambahkan informasi ini sesederhana ini:

df = pd.read_csv(meaningless_test)
metadata = {'fw': foo, 'test_name': bar, 'scenario': sc_01}
ds = xr.Dataset.from_dataframe(df)
ds.attrs = metadata
jtwilson.dll
sumber
2

Saya telah mencari solusi dan menemukan bahwa bingkai panda memiliki properti attrs

pd.DataFrame().attrs.update({'your_attribute' : 'value'})
frame.attrs['your_attribute']

Atribut ini akan selalu menempel pada bingkai Anda setiap kali Anda melewatinya!

Ayrat Arifullin
sumber
Perhatikan bahwa attrs bersifat eksperimental dan dapat berubah tanpa peringatan, tetapi ini adalah solusi yang sangat sederhana. Saya ingin tahu apakah attrs ditransfer ke dataframe baru.
Liquidgenius
Sayangnya, attrs tidak disalin ke kerangka data baru :(
Adam
1

Saya mengalami masalah yang sama dan menggunakan solusi untuk membuat DF baru yang lebih kecil dari kamus dengan metadata:

    meta = {"name": "Sample Dataframe", "Created": "19/07/2019"}
    dfMeta = pd.DataFrame.from_dict(meta, orient='index')

DfMeta ini kemudian dapat disimpan bersama DF asli Anda dalam acar dll

Lihat Menyimpan dan memuat banyak objek dalam file acar? (Jawaban Lutz) untuk jawaban luar biasa tentang menyimpan dan mengambil beberapa kerangka data menggunakan acar

SenAnan
sumber