是否可以向熊猫DataFrame添加一些元信息/元数据?
例如,用于测量数据的仪器名称,负责的仪器等。
一种解决方法是用该信息创建一列,但是在每一行中存储一条信息似乎很浪费!
Answers:
当然,像大多数Python对象一样,您可以将新属性附加到pandas.DataFrame
:
import pandas as pd
df = pd.DataFrame([])
df.instrument_name = 'Binky'
但是请注意,虽然可以附加属性的数据帧,操作上数据帧进行(如groupby
,pivot
,join
或loc
仅举几例)可能会返回一个新的数据帧没有连接的元数据。熊猫还没有一种可靠的方法来传播 附加到DataFrames的元数据。
可以将元数据保存在文件中。您可以在此处找到有关如何将元数据存储在HDF5文件中的示例。
store = pd.HDFStore(...)
,则可以使用存储属性store.root._v_attrs.key = value
。
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 = {}
)。
自己碰到这个问题。从熊猫0.13开始,DataFrame在其上具有_metadata属性,该属性确实会通过返回新DataFrames的函数来保留。似乎也可以在序列化中幸存下来(我只尝试过json,但我想hdf也被覆盖了)。
_metadata
不是公共API的一部分,因此强烈建议您不要依赖此功能。
_metadata
实际上是一个类属性,而不是实例属性。因此DataFrame
,只要模块保持加载状态,新实例就会从以前的实例继承。请勿_metadata
用于任何用途。+1 xarray
!
并不是的。尽管您可以像@unutbu提到的那样将包含元数据的属性添加到DataFrame类中,但是许多DataFrame方法返回一个新的DataFrame,因此您的元数据将丢失。如果您需要操纵数据框,那么最好的选择是将元数据和数据框包装在另一个类中。在GitHub上查看此讨论:https : //github.com/pydata/pandas/issues/2485
当前有一个打开的拉取请求,用于添加MetaDataFrame对象,该对象将更好地支持元数据。
从熊猫1.0(可能更早)开始,现在有一个Dataframe.attrs
属性。这是实验性的,但这可能是您将来想要的。例如:
import pandas as pd
df = pd.DataFrame([])
df.attrs['instrument_name'] = 'Binky'
在此处的文档中找到它。
to_parquet
然后再尝试使用from_parquet
,它似乎并不持久,因此请确保使用用例进行验证。
dataclass
作为元数据,然后子类化DataFrame
以像您共享的帖子中那样进行加载/转储的方法可能是一个不错的解决方案。
将任意属性附加到DataFrame对象的最佳答案是好的,但是如果使用字典,列表或元组,它将发出错误“ Pandas不允许通过新的属性名称创建列”。以下解决方案适用于存储任意属性。
from types import SimpleNamespace
df = pd.DataFrame()
df.meta = SimpleNamespace()
df.meta.foo = [1,2,3]
pd.DataFrame._metadata += ["meta"]
。请注意,这部分是Pandas的属性,而不是您特定数据
df.meta
会触发警告,Pandas不允许以这种方式生成新列。
df.meta
是SimpleNamespace,因此不会触发该警告。熊猫不会尝试从中建立专栏。
正如其他答案和评论中所提到的那样,_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
谈到这一点很晚,我认为如果您需要元数据来通过I / O持久化,这可能会有所帮助。我一直使用一个相对较新的软件包h5io来完成此任务。
它应该使您能够从HDF5快速读取/写入几种常见格式,其中一种是数据帧。因此,例如,您可以将数据框放入字典中,并将元数据作为字段包含在字典中。例如:
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。
我一直在寻找解决方案,发现熊猫框架具有该属性 attrs
pd.DataFrame().attrs.update({'your_attribute' : 'value'})
frame.attrs['your_attribute']
只要您通过此属性,它就会始终粘贴在您的框架上!
我遇到了同样的问题,并使用了一种变通方法,该方法是使用元数据从字典中创建一个新的,较小的DF:
meta = {"name": "Sample Dataframe", "Created": "19/07/2019"}
dfMeta = pd.DataFrame.from_dict(meta, orient='index')
然后可以将此dfMeta与原始DF一起保存在pickle中。
请参阅在pickle文件中保存和加载多个对象?(Lutz的答案)对于使用pickle保存和检索多个数据帧的出色答案