将元信息/元数据添加到pandas DataFrame中

P3t*_*rus 73 python pandas

是否可以向pandas DataFrame添加一些元信息/元数据?

例如,用于测量数据的仪器名称,负责的仪器等.

一种解决方法是创建一个包含该信息的列,但在每一行中存储单条信息似乎很浪费!

unu*_*tbu 70

当然,像大多数Python对象一样,您可以将新属性附加到pandas.DataFrame:

import pandas as pd
df = pd.DataFrame([])
df.instrument_name = 'Binky'
Run Code Online (Sandbox Code Playgroud)

但是请注意,虽然可以附加属性的数据帧,操作上数据帧进行(如groupby,pivot,joinloc以仅举几例)可能会返回一个新的数据帧没有连接的元数据.Pandas还没有一种强大的方法来传播 附加到DataFrames的元数据.

可以保留文件中的元数据.您可以在此处找到有关如何在HDF5文件中存储元数据的示例.

  • +1为您选择仪器名称!您是否有尝试将这些额外属性转储到HDFStore的经验? (4认同)
  • @DanAllan:如果`store = pd.HDFStore(...)`,那么属性可以用`store.root._v_attrs.key = value`存储. (4认同)
  • 对于其他可能使用此功能的人:文档添加了一个相关部分.http://pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore (3认同)
  • [对于子孙后代,在v0.18.1中进行酸洗时不会保留这一点](http://stackoverflow.com/questions/31727333/get-the-name-of-the-dataframe-python/31727504#comment70185470_31727504). (3认同)
  • 在pandas 0.23.1中,通过分配字典,列表或元组来创建新属性会发出警告(即df = pd.DataFrame(); df.meta = {}`会产生UserWarning:Pandas不允许使用列通过新的属性名称创建-请参见https:// pandas.pydata.org / pandas-docs / stable / indexing.html#attribute-access`)。(如果已经按照`df = pd.DataFrame(); df.meta =''; df.meta = {}`的方式创建了属性,则不会发出警告)。 (2认同)
  • 最令人惊讶的是,“df.copy()”也不保留自定义属性。 (2认同)
  • 目前有一个实验性属性 `.attrs` 应该可以做到这一点:https://pandas.pydata.org/pandas-docs/stable/reference/frame.html#metadata (2认同)

rya*_*lon 31

从 pandas 1.0 开始,可能更早,现在有一个Dataframe.attrs属性。这是实验性的,但这可能是您将来想要的。例如:

import pandas as pd
df = pd.DataFrame([])
df.attrs['instrument_name'] = 'Binky'
Run Code Online (Sandbox Code Playgroud)

此处的文档中找到它。

尝试使用to_parquet然后from_parquet,它似乎不会持续存在,所以一定要检查你的用例。

  • @rdmolony 太棒了。我认为使用“dataclass”作为元数据,然后对“DataFrame”进行子类化,让一个方法执行加载/转储,就像您共享的帖子中那样,可能是一个不错的解决方案。 (3认同)
  • 您可能会发现此[Stackoverflow讨论](/sf/ask/3648587211/)很有用,因为它演示了如何在需要时将自定义元数据添加到镶木地板文件中 (2认同)
  • 这很好。与接受的答案相反,这确实在保存并从 pickle 加载后保留了属性! (2认同)
  • 通过“to_feather()”存储时它不是持久的。 (2认同)

fol*_*oof 11

我自己也遇到过这个问题.从pandas 0.13开始,DataFrames上有一个_metadata属性,它通过返回新DataFrames的函数继续存在.似乎还能幸免于序列化(我只尝试了json,但我想hdf也被覆盖了).

  • `_metadata`不是公共API的一部分,因此我强烈建议不要依赖此功能. (14认同)
  • `_metadata`实际上是一个类属性,而不是一个实例属性.因此,只要模块保持加载,新的`DataFrame`实例就会继承先前的实例.不要使用`_metadata`来做任何事情.为'xarray` +1! (11认同)

Mat*_*ohn 10

并不是的.虽然您可以将包含元数据的属性添加到DataFrame类作为@unutbu提及,但许多DataFrame方法会返回一个新的DataFrame,因此您的元数据将会丢失.如果您需要操作数据框,那么最好的选择是将元数据和DataFrame包装在另一个类中.请参阅GitHub上的讨论:https://github.com/pydata/pandas/issues/2485

目前有一个打开拉取请求来添加MetaDataFrame对象,这将更好地支持元数据.


bsc*_*can 9

将任意属性附加到 DataFrame 对象的最佳答案是好的,但是如果您使用字典、列表或元组,它将发出错误“Pandas 不允许通过新的属性名称创建列”。以下解决方案适用于存储任意属性。

from types import SimpleNamespace
df = pd.DataFrame()
df.meta = SimpleNamespace()
df.meta.foo = [1,2,3]
Run Code Online (Sandbox Code Playgroud)


Den*_*zov 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)
Run Code Online (Sandbox Code Playgroud)

输出:

val
1    my_value
2    my_value
3    my_value
dtype: object
Run Code Online (Sandbox Code Playgroud)


小智 6

正如@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
Run Code Online (Sandbox Code Playgroud)


kee*_*ive 5

请参考定义原始属性Pandas 官方文档部分,如果可以选择子类化pandas.DataFrame请注意:

为了让原始数据结构具有附加属性,您应该知道pandas添加了哪些属性。

因此,您可以做的事情(任意选择名称MetaedDataFrame)是

class MetaedDataFrame(pd.DataFrame):
    """s/e."""
    _metadata = ['instrument_name']

    @property
    def _constructor(self):
        return self.__class__

    # Define the following if providing attribute(s) at instantiation
    # is a requirement, otherwise, if YAGNI, don't.
    def __init__(
        self, *args, instrument_name: str = None, **kwargs
    ):
        super().__init__(*args, **kwargs)
        self.instrument_name = instrument_name
Run Code Online (Sandbox Code Playgroud)

然后用你的(_metadata-prespecified)属性实例化你的数据框

>>> mdf = MetaedDataFrame(instrument_name='Binky')
>>> mdf.instrument_name
'Binky'
Run Code Online (Sandbox Code Playgroud)

或者甚至在实例化之后

>>> mdf = MetaedDataFrame()
>>> mdf.instrument_name = 'Binky'
'Binky'
Run Code Online (Sandbox Code Playgroud)

没有任何类型的警告(截至 2021 年 6 月 15 日):连载~.copy像魅力一样工作。此外,这种方法还可以丰富您的 API,例如通过向instrument_name中添加一些基于 - 的成员MetaedDataFrame,例如属性(或方法):

    [...]
    
    @property
    def lower_instrument_name(self) -> str:
        if self.instrument_name is not None:
            return self.instrument_name.lower()

    [...]
Run Code Online (Sandbox Code Playgroud)
>>> mdf.lower_instrument_name
'binky'
Run Code Online (Sandbox Code Playgroud)

...但这超出了这个问题的范围...


归档时间:

查看次数:

27709 次

最近记录:

6 年,1 月 前