Thêm siêu thông tin / siêu dữ liệu vào DataFrame của gấu trúc


90

Có thể thêm một số siêu thông tin / siêu dữ liệu vào DataFrame của gấu trúc không?

Ví dụ: tên của công cụ được sử dụng để đo dữ liệu, công cụ chịu trách nhiệm, v.v.

Một cách giải quyết là tạo một cột với thông tin đó, nhưng có vẻ lãng phí nếu lưu trữ một phần thông tin trong mỗi hàng!


Vui lòng lưu ý câu trả lời @ryanjdillon (hiện đang bị chôn vùi gần cuối) đề cập đến thuộc tính thử nghiệm được cập nhật 'attrs', có vẻ như là một sự khởi đầu, có thể
JohnE

Câu trả lời:


85

Chắc chắn, giống như hầu hết các đối tượng Python, bạn có thể đính kèm các thuộc tính mới vào pandas.DataFrame:

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

Lưu ý, tuy nhiên, trong khi bạn có thể đính kèm các thuộc tính cho một DataFrame, các hoạt động thực hiện trên DataFrame (ví dụ như groupby, pivot, joinhoặc locđể đặt tên chỉ là một vài) có thể trả về một DataFrame mới mà không siêu dữ liệu kèm theo. Pandas vẫn chưa có phương pháp truyền siêu dữ liệu mạnh mẽ được gắn vào DataFrames .

Có thể lưu siêu dữ liệu trong một tệp . Bạn có thể tìm thấy ví dụ về cách lưu trữ siêu dữ liệu trong tệp HDF5 tại đây .


5
+1 cho bạn lựa chọn tên nhạc cụ! Bạn có bất kỳ kinh nghiệm nào cố gắng kết xuất các thuộc tính bổ sung này vào HDFStore không?
Dan Allan

4
@DanAllan: Nếu store = pd.HDFStore(...), thì các thuộc tính có thể được lưu trữ với store.root._v_attrs.key = value.
unutbu

3
Đối với bất kỳ ai khác có thể sử dụng tài liệu này: tài liệu đã thêm một phần về điều này. pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore
Dan Allan


4
Trong pandas 0.23.1, việc tạo một thuộc tính mới bằng cách gán một từ điển, danh sách hoặc tuple sẽ đưa ra một cảnh báo (tức là df = pd.DataFrame(); df.meta = {}tạo ra 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). (Không có cảnh báo nào được đưa ra nếu thuộc tính đã được tạo như trong df = pd.DataFrame(); df.meta = ''; df.meta = {}).
teichert

13

Tôi chỉ gặp vấn đề này. Kể từ gấu trúc 0.13, DataFrames có một thuộc tính _metadata trên chúng mà vẫn tồn tại thông qua các hàm trả về DataFrames mới. Cũng có vẻ như để tồn tại tuần tự tốt (tôi chỉ thử json, nhưng tôi tưởng tượng hdf cũng được bảo hiểm).


16
_metadatakhông phải là một phần của API công khai, vì vậy tôi thực sự khuyên bạn không nên dựa vào chức năng này.
shoyer

@Stephan, bạn có thể giải thích thêm về điều đó được không? Tại sao điều quan trọng là trở thành một phần của API công khai? Câu nói của bạn có đúng với phiên bản 0.15 không?
TomCho

1
@TomCho vâng, câu trả lời đó vẫn đúng cho đến ngày nay. Bạn có thể có một cái nhìn tại tia X ( github.com/xray/xray ) cho một ví dụ khác của một mảng dán nhãn mà hỗ trợ siêu dữ liệu, đặc biệt là nếu bạn có dữ liệu đa chiều ( .attrslà một phần của API tia X)
shoyer

17
_metadatathực sự là một thuộc tính lớp, không phải là một thuộc tính cá thể. Vì vậy, các DataFramephiên bản mới kế thừa từ các phiên bản trước, miễn là mô-đun vẫn được tải. Không sử dụng _metadatacho bất cứ điều gì. +1 cho xarray!
j08lue

1
_metadata - một tính năng không được hỗ trợ đã cứu một ngày của tôi! Cảm ơn bạn.
joctee

12

Không hẳn. Mặc dù bạn có thể thêm các thuộc tính chứa siêu dữ liệu vào lớp DataFrame như @unutbu đã đề cập, nhiều phương thức DataFrame trả về một DataFrame mới, do đó, siêu dữ liệu của bạn sẽ bị mất. Nếu bạn cần thao tác khung dữ liệu của mình, thì tùy chọn tốt nhất sẽ là bọc siêu dữ liệu và DataFrame của bạn trong một lớp khác. Xem cuộc thảo luận này trên GitHub: https://github.com/pydata/pandas/issues/2485

Hiện có một yêu cầu kéo mở để thêm đối tượng MetaDataFrame, đối tượng này sẽ hỗ trợ siêu dữ liệu tốt hơn.


11

Kể từ pandas 1.0, có thể sớm hơn, bây giờ có một thuộc Dataframe.attrstính. Nó là thử nghiệm, nhưng đây có thể là những gì bạn sẽ muốn trong tương lai. Ví dụ:

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

Tìm nó trong tài liệu ở đây .

to_parquetSau đó from_parquet, hãy thử điều này và sau đó , nó dường như không tiếp tục, vì vậy hãy đảm bảo bạn kiểm tra điều đó với trường hợp sử dụng của mình.


Điều này thật thú vị và dường như vẫn tồn tại đối với copy / loc / iloc, nhưng không phải đối với groupby.
JohnE

Chỉ là một gợi ý, nhưng có thể hiển thị một ví dụ về cách sử dụng nó? Tài liệu về cơ bản là không có gì, nhưng chỉ cần thử với nó, tôi có thể thấy rằng nó được khởi tạo như một từ điển trống và nó dường như được thiết lập để nó phải là một từ điển mặc dù tất nhiên người ta có thể lồng một danh sách vào bên trong nó, ví dụ.
JohnE

1
Bạn có thể tìm thấy điều này thảo luận Stackoverflow hữu ích vì nó cho thấy làm thế nào để thêm siêu dữ liệu tùy chỉnh các tập tin sàn gỗ nếu cần
rdmolony

1
@rdmolony Thật tuyệt. Tôi nghĩ rằng sử dụng một dataclasscho siêu dữ liệu và sau đó phân lớp DataFrameđể có một phương thức thực hiện tải / kết xuất như trong bài đăng mà bạn đã chia sẻ có thể là một giải pháp tốt.
ryanjdillon

1
Cái này đẹp đấy. Ngược lại với câu trả lời được chấp nhận, điều này bảo toàn thuộc tính sau khi lưu và tải từ dưa chua!
CGFoX

8

Câu trả lời hàng đầu của việc gắn các thuộc tính tùy ý vào đối tượng DataFrame là tốt, nhưng nếu bạn sử dụng từ điển, danh sách hoặc tuple, nó sẽ phát ra lỗi "Pandas không cho phép tạo cột thông qua tên thuộc tính mới". Giải pháp sau đây hoạt động để lưu trữ các thuộc tính tùy ý.

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

Ngoài ra, nếu bạn muốn điều này tồn tại trên các bản sao của khung dữ liệu của mình, bạn cần phải làm pd.DataFrame._metadata += ["meta"]. Lưu ý rằng phần này là thuộc tính của Gấu trúc, không phải thuộc tính của khung dữ liệu cụ thể của bạn
bscan 19/02/19

Cách tiếp cận này sẽ không hoạt động nữa vì df.metakích hoạt cảnh báo rằng Pandas không cho phép các cột mới được tạo theo cách này.
anishtain 4

@ anishtain4, tôi vừa thử nghiệm nó với Pandas 25.1 (được phát hành ~ 2 tuần trước) và mã này vẫn hoạt động với tôi. Cảnh báo đó không được kích hoạt vì df.metalà một SimpleNamespace. Gấu trúc sẽ không thử và xây dựng một cột từ nó.
bscan

6

Như đã đề cập trong các câu trả lời và nhận xét khác, _metadatanó không phải là một phần của API công khai, vì vậy chắc chắn không phải là ý kiến ​​hay khi sử dụng nó trong môi trường sản xuất. Nhưng bạn vẫn có thể muốn sử dụng nó trong quá trình tạo mẫu nghiên cứu và thay thế nó nếu nó ngừng hoạt động. Và ngay bây giờ nó hoạt động với groupby/ apply, rất hữu ích. Đây là một ví dụ (mà tôi không thể tìm thấy trong các câu trả lời khác):

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)

Đầu ra:

val
1    my_value
2    my_value
3    my_value
dtype: object

4

Đến khá muộn với việc này, tôi nghĩ điều này có thể hữu ích nếu bạn cần siêu dữ liệu để duy trì I / O. Có một gói tương đối mới có tên h5io mà tôi đang sử dụng để thực hiện điều này.

Nó sẽ cho phép bạn đọc / ghi nhanh từ HDF5 đối với một số định dạng phổ biến, một trong số chúng là khung dữ liệu. Vì vậy, bạn có thể, chẳng hạn, đặt khung dữ liệu vào từ điển và bao gồm siêu dữ liệu dưới dạng các trường trong từ điển. Ví dụ:

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

Một lựa chọn khác sẽ là xem xét một dự án như xray , theo một số cách thì phức tạp hơn, nhưng tôi nghĩ nó cho phép bạn sử dụng siêu dữ liệu và khá dễ dàng để chuyển đổi thành DataFrame.


4

Như đã đề cập bởi @choldgraf, tôi thấy xarray là một công cụ tuyệt vời để đính kèm siêu dữ liệu khi so sánh dữ liệu và vẽ kết quả giữa một số khung dữ liệu.

Trong công việc của tôi, chúng tôi thường so sánh kết quả của một số bản sửa đổi chương trình cơ sở và các tình huống thử nghiệm khác nhau, việc thêm thông tin này đơn giản như sau:

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

Tôi đã tìm kiếm một giải pháp và nhận thấy rằng khung gấu trúc có thuộc tính attrs

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

Thuộc tính này sẽ luôn dính vào khung của bạn bất cứ khi nào bạn vượt qua nó!


Lưu ý rằng attrs là thử nghiệm và có thể thay đổi mà không cần cảnh báo trước, nhưng đây là một giải pháp rất đơn giản. Tôi tự hỏi liệu các tập tin có chuyển sang khung dữ liệu mới không.
Liquidgenius

Rất tiếc, phần đính kèm không được sao chép vào khung dữ liệu mới :(
Adam

1

Tôi đang gặp vấn đề tương tự và đã sử dụng một giải pháp khác là tạo DF mới, nhỏ hơn từ một từ điển với siêu dữ liệu:

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

Sau đó, dfMeta này có thể được lưu cùng với DF ban đầu của bạn trong dưa chua, v.v.

Xem Lưu và tải nhiều đối tượng trong tệp dưa chua? (Câu trả lời của Lutz) cho câu trả lời tuyệt vời về cách lưu và truy xuất nhiều khung dữ liệu bằng cách sử dụng pickle

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.