是否可以向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
,join
或loc
以仅举几例)可能会返回一个新的数据帧没有连接的元数据.Pandas还没有一种强大的方法来传播 附加到DataFrames的元数据.
可以保留文件中的元数据.您可以在此处找到有关如何在HDF5文件中存储元数据的示例.
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
,它似乎不会持续存在,所以一定要检查你的用例。
fol*_*oof 11
我自己也遇到过这个问题.从pandas 0.13开始,DataFrames上有一个_metadata属性,它通过返回新DataFrames的函数继续存在.似乎还能幸免于序列化(我只尝试了json,但我想hdf也被覆盖了).
Mat*_*ohn 10
并不是的.虽然您可以将包含元数据的属性添加到DataFrame类作为@unutbu提及,但许多DataFrame方法会返回一个新的DataFrame,因此您的元数据将会丢失.如果您需要操作数据框,那么最好的选择是将元数据和DataFrame包装在另一个类中.请参阅GitHub上的讨论:https://github.com/pydata/pandas/issues/2485
目前有一个打开拉取请求来添加MetaDataFrame对象,这将更好地支持元数据.
将任意属性附加到 DataFrame 对象的最佳答案是好的,但是如果您使用字典、列表或元组,它将发出错误“Pandas 不允许通过新的属性名称创建列”。以下解决方案适用于存储任意属性。
from types import SimpleNamespace
df = pd.DataFrame()
df.meta = SimpleNamespace()
df.meta.foo = [1,2,3]
Run Code Online (Sandbox Code Playgroud)
正如其他答案和评论中所述,_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)
请参考定义原始属性(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 次 |
最近记录: |