การเพิ่มข้อมูลเมตา / ข้อมูลเมตาให้กับแพนด้า DataFrame


92

เป็นไปได้ไหมที่จะเพิ่มข้อมูลเมตา / ข้อมูลเมตาลงใน DataFrame ของแพนด้า

ตัวอย่างเช่นชื่อเครื่องมือที่ใช้ในการวัดข้อมูลเครื่องมือที่รับผิดชอบเป็นต้น

วิธีแก้ปัญหาอย่างหนึ่งคือการสร้างคอลัมน์ที่มีข้อมูลนั้น แต่ดูเหมือนว่าจะสิ้นเปลืองที่จะจัดเก็บข้อมูลชิ้นเดียวในทุกแถว!


โปรดสังเกตคำตอบของ @ryanjdillon (ปัจจุบันถูกฝังไว้ที่ด้านล่าง) ซึ่งกล่าวถึงแอตทริบิวต์การทดลองที่อัปเดต 'attrs' ซึ่งดูเหมือนจะเป็นการเริ่มต้นบางที
JohnE

คำตอบ:


87

แน่นอนเช่นเดียวกับวัตถุ Python ส่วนใหญ่คุณสามารถแนบแอตทริบิวต์ใหม่กับpandas.DataFrame:

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

แต่โปรดทราบว่าในขณะที่คุณสามารถแนบแอตทริบิวต์ DataFrame ให้การดำเนินการดำเนินการใน DataFrame (เช่นgroupby, pivot, joinหรือlocเพื่อชื่อเพียงไม่กี่) อาจส่งคืน DataFrame ใหม่โดยไม่ต้องเมตาดาต้าที่แนบมา นุ่นยังไม่ได้มีวิธีการที่แข็งแกร่งของการแพร่กระจาย ข้อมูลเมตาที่แนบมากับ DataFrames

การเก็บรักษาข้อมูลเมตาในไฟล์เป็นไปได้ คุณสามารถค้นหาตัวอย่างของวิธีการในการจัดเก็บข้อมูลเมตาในไฟล์ HDF5 ที่นี่


5
+1 ให้คุณเลือกชื่อเครื่องดนตรี! คุณมีประสบการณ์ในการพยายามทิ้งแอตทริบิวต์พิเศษเหล่านี้ลงใน HDFStore หรือไม่?
Dan Allan

4
@DanAllan: หากstore = pd.HDFStore(...)สามารถเก็บแอตทริบิวต์ด้วยstore.root._v_attrs.key = valueไฟล์.
unutbu

3
สำหรับคนอื่นที่อาจใช้สิ่งนี้: เอกสารได้เพิ่มส่วนในเรื่องนี้ pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore
Dan Allan


5
ในแพนด้า 0.23.1 การสร้างแอตทริบิวต์ใหม่โดยการกำหนดพจนานุกรมรายการหรือทูเพิลจะให้คำเตือน (เช่นdf = pd.DataFrame(); df.meta = {}ผลิต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) (ไม่มีการแจ้งเตือนหากมีการสร้างแอตทริบิวต์ดังกล่าวแล้วdf = pd.DataFrame(); df.meta = ''; df.meta = {})
teichert

14

สำหรับแพนด้า 1.0 อาจจะก่อนหน้านี้ตอนนี้มีDataframe.attrsคุณสมบัติ เป็นการทดลอง แต่นี่อาจเป็นสิ่งที่คุณต้องการในอนาคต ตัวอย่างเช่น:

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

พบว่าในเอกสารที่นี่

ลองใช้to_parquetแล้วfrom_parquetดูเหมือนว่าจะไม่เกิดขึ้นดังนั้นโปรดตรวจสอบกับกรณีการใช้งานของคุณ


สิ่งนี้น่าสนใจและดูเหมือนจะยังคงมีอยู่สำหรับ copy / loc / iloc แต่ไม่ใช่สำหรับ groupby
JohnE

แค่คำแนะนำ แต่อาจจะแสดงตัวอย่างวิธีการใช้งาน? เอกสารนั้นไม่มีอะไรเป็นพื้นฐาน แต่จากการเล่นกับมันฉันเห็นได้ว่ามันเริ่มต้นเป็นพจนานุกรมว่างเปล่าและดูเหมือนว่าจะถูกตั้งค่าเพื่อให้มันต้องเป็นพจนานุกรมแม้ว่าแน่นอนว่าจะมีรายการอยู่ในนั้น ตัวอย่างเช่น.
JohnE

1
คุณอาจพบว่าการสนทนา Stackoverflowนี้มีประโยชน์เนื่องจากสาธิตวิธีการเพิ่มข้อมูลเมตาที่กำหนดเองให้กับไฟล์ปาร์เก้หากจำเป็น
rdmolony

1
@rdmolony เยี่ยมมาก ฉันคิดว่าการใช้ a dataclassสำหรับข้อมูลเมตาแล้วซับคลาสDataFrameเพื่อให้มีวิธีการโหลด / การถ่ายโอนข้อมูลเหมือนในโพสต์ที่คุณแชร์อาจเป็นทางออกที่ดี
ryanjdillon

1
นี่เป็นสิ่งที่ดี ตรงกันข้ามกับคำตอบที่ได้รับการยอมรับสิ่งนี้จะเก็บรักษาคุณสมบัติไว้หลังจากบันทึกและโหลดจากของดอง!
CGFoX

13

เพิ่งพบปัญหานี้ด้วยตัวเอง ในฐานะแพนด้า 0.13 DataFrames มีแอตทริบิวต์ _metadata ซึ่งจะคงอยู่ผ่านฟังก์ชันที่ส่งคืน DataFrames ใหม่ ดูเหมือนว่าจะรอดจากการทำให้เป็นอนุกรมได้ดี (ฉันลองใช้ json เท่านั้น แต่ฉันคิดว่า hdf ครอบคลุมด้วยเช่นกัน)


16
_metadataไม่ได้เป็นส่วนหนึ่งของ API สาธารณะดังนั้นฉันจึงไม่แนะนำให้ใช้ฟังก์ชันนี้
shoyer

@Stephan ช่วยอธิบายให้ละเอียดหน่อยได้ไหม? เหตุใดการเป็นส่วนหนึ่งของ API สาธารณะจึงสำคัญ คำแถลงของคุณเป็นจริงสำหรับเวอร์ชัน 0.15 หรือไม่
TomCho

1
@ ทอมโชใช่คำตอบนั้นยังคงเป็นจริงในวันนี้ คุณอาจดูที่ xray ( github.com/xray/xray ) สำหรับตัวอย่างทางเลือกหนึ่งของอาร์เรย์ที่มีป้ายกำกับที่รองรับข้อมูลเมตาโดยเฉพาะอย่างยิ่งหากคุณมีข้อมูลหลายมิติ ( .attrsเป็นส่วนหนึ่งของ xray API)
shoyer

17
_metadataเป็นแอตทริบิวต์คลาสไม่ใช่แอตทริบิวต์อินสแตนซ์ ดังนั้นDataFrameอินสแตนซ์ใหม่จะสืบทอดมาจากอินสแตนซ์ก่อนหน้าตราบใดที่โมดูลยังคงโหลดอยู่ ห้ามใช้_metadataเพื่ออะไร +1 สำหรับxarray!
j08lue

1
_metadata - คุณสมบัติที่ไม่รองรับที่ช่วยชีวิตฉันไว้! ขอขอบคุณ.
joctee

12

ไม่จริง. แม้ว่าคุณจะสามารถเพิ่มแอตทริบิวต์ที่มีข้อมูลเมตาให้กับคลาส DataFrame ได้ตามที่ @unutbu กล่าวถึง แต่เมธอด DataFrame จำนวนมากจะส่งคืน DataFrame ใหม่ดังนั้นข้อมูลเมตาของคุณจะสูญหายไป หากคุณต้องการจัดการดาต้าเฟรมของคุณตัวเลือกที่ดีที่สุดคือการรวมข้อมูลเมตาและ DataFrame ของคุณไว้ในคลาสอื่น ดูการสนทนานี้ใน GitHub: https://github.com/pydata/pandas/issues/2485

ขณะนี้มีคำขอดึงแบบเปิดเพื่อเพิ่มวัตถุ MetaDataFrame ซึ่งจะรองรับข้อมูลเมตาได้ดีขึ้น


8

คำตอบอันดับต้น ๆ ของการแนบแอตทริบิวต์ที่กำหนดเองกับวัตถุ DataFrame เป็นสิ่งที่ดี แต่ถ้าคุณใช้พจนานุกรมรายการหรือทูเพิลก็จะแสดงข้อผิดพลาด "Pandas ไม่อนุญาตให้สร้างคอลัมน์ผ่านชื่อแอตทริบิวต์ใหม่" โซลูชันต่อไปนี้ใช้สำหรับจัดเก็บแอตทริบิวต์โดยพลการ

from types import SimpleNamespace
df = pd.DataFrame()
df.meta = SimpleNamespace()
df.meta.foo = [1,2,3]

นอกจากนี้ถ้าคุณอยากให้เรื่องนี้ยังคงมีอยู่ทั่วสำเนาของ dataframe pd.DataFrame._metadata += ["meta"]ของคุณที่คุณต้องทำ โปรดทราบว่าส่วนนี้เป็นแอตทริบิวต์ของ Pandas ไม่ใช่แอตทริบิวต์ของดาต้าเฟรมเฉพาะของคุณ
bscan

วิธีนี้จะใช้ไม่ได้อีกต่อไปเนื่องจากdf.metaมีการเตือนว่า Pandas ไม่อนุญาตให้สร้างคอลัมน์ใหม่ด้วยวิธีนี้
anishtain4

@ anishtain4 ฉันเพิ่งทดสอบกับ Pandas 25.1 (เปิดตัว ~ 2 สัปดาห์ที่แล้ว) และรหัสนี้ยังใช้ได้กับฉัน คำเตือนนั้นไม่ถูกเรียกใช้เนื่องจากdf.metaเป็น SimpleNamespace นุ่นจะไม่พยายามสร้างคอลัมน์จากมัน
bscan

6

ดังที่กล่าวไว้ในคำตอบและความคิดเห็นอื่น ๆ_metadataไม่ใช่ส่วนหนึ่งของ API สาธารณะดังนั้นจึงไม่ควรใช้ในสภาพแวดล้อมการผลิต แต่คุณอาจต้องการใช้ในการสร้างต้นแบบการวิจัยและแทนที่หากมันหยุดทำงาน และตอนนี้มันใช้งานได้กับgroupby/ applyซึ่งมีประโยชน์ นี่คือตัวอย่าง (ซึ่งฉันไม่พบคำตอบอื่น ๆ ):

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)

เอาท์พุต:

val
1    my_value
2    my_value
3    my_value
dtype: object

4

การมาช้าไปหน่อยฉันคิดว่านี่อาจเป็นประโยชน์หากคุณต้องการข้อมูลเมตาเพื่อคงอยู่เหนือ I / O มีแพ็คเกจใหม่ที่เรียกว่าh5ioที่ฉันใช้เพื่อทำสิ่งนี้ให้สำเร็จ

ควรช่วยให้คุณอ่าน / เขียนได้อย่างรวดเร็วจาก HDF5 สำหรับรูปแบบทั่วไปสองสามรูปแบบหนึ่งในนั้นคือ dataframe ตัวอย่างเช่นคุณสามารถใส่ dataframe ในพจนานุกรมและรวมข้อมูลเมตาเป็นช่องในพจนานุกรมได้ เช่น:

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...

อีกทางเลือกหนึ่งคือการดูโปรเจ็กต์เช่นxrayซึ่งมีความซับซ้อนกว่าในบางวิธี แต่ฉันคิดว่ามันช่วยให้คุณใช้ข้อมูลเมตาและแปลงเป็น DataFrame ได้ค่อนข้างง่าย


4

ดังที่ได้กล่าวไว้โดย @choldgraf ฉันพบว่าxarrayเป็นเครื่องมือที่ยอดเยี่ยมสำหรับการแนบข้อมูลเมตาเมื่อเปรียบเทียบข้อมูลและการลงจุดผลลัพธ์ระหว่างดาต้าเฟรมหลาย ๆ

ในงานของฉันเรามักจะเปรียบเทียบผลลัพธ์ของการแก้ไขเฟิร์มแวร์หลายรายการและสถานการณ์การทดสอบที่แตกต่างกันการเพิ่มข้อมูลนี้ทำได้ง่ายๆดังนี้:

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

2

ฉันได้หาวิธีแก้ไขและพบว่าแพนด้ากรอบมีคุณสมบัติ attrs

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

แอตทริบิวต์นี้จะติดอยู่กับเฟรมของคุณทุกครั้งที่คุณผ่าน!


โปรดทราบว่า attrs อยู่ในช่วงทดลองและอาจเปลี่ยนแปลงโดยไม่มีการเตือนล่วงหน้า แต่นี่เป็นวิธีแก้ปัญหาที่ง่าย ฉันสงสัยว่า Attrs โอนไปยังดาต้าเฟรมใหม่หรือไม่
Liquidgenius

น่าเสียดายที่ Attrs ไม่ได้คัดลอกไปยังดาต้าเฟรมใหม่ :(
อดัม

1

ฉันมีปัญหาเดียวกันและใช้วิธีแก้ปัญหาในการสร้าง DF ใหม่ที่เล็กกว่าจากพจนานุกรมด้วยข้อมูลเมตา:

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

จากนั้น dfMeta นี้สามารถบันทึกควบคู่ไปกับ DF ดั้งเดิมของคุณในดอง ฯลฯ

โปรดดูที่การบันทึกและโหลดวัตถุหลายรายการในไฟล์ดองหรือไม่ (คำตอบของ Lutz) สำหรับคำตอบที่ยอดเยี่ยมเกี่ยวกับการบันทึกและการดึงข้อมูลหลายดาต้าเฟรมโดยใช้ดอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.