python - 通过连接传播 pandas 系列元数据

标签 python pandas metadata

我希望能够将元数据附加到数据帧系列(特别是原始文件名),以便在加入两个数据帧后,我可以看到每个系列来自何处的元数据。

我看到有关 _metadata(herehere)的 github 问题,包括一些与当前 _metadata 属性(here)相关的问题,但在 Pandas 文档。

到目前为止,我可以修改 _metadata 属性以允许保留元数据,但在加入后得到一个 AttributeError

df1 = pd.DataFrame(np.random.randint(0, 4, (6, 3)))
df2 = pd.DataFrame(np.random.randint(0, 4, (6, 3)))
df1._metadata.append('filename')
df1[df1.columns[0]]._metadata.append('filename')

for c in df1:
    df1[c].filename = 'fname1.csv'
    df2[c].filename = 'fname2.csv'

df1[0]._metadata  # ['name', 'filename']
df1[0].filename  # fname1.csv
df2[0].filename  # fname2.csv
df1[0][:3].filename  # fname1.csv

mgd = pd.merge(df1, df2, on=[0])
mgd['1_x']._metadata  # ['name', 'filename']
mgd['1_x'].filename  # raises AttributeError

有什么方法可以保留它吗?

更新:结语

讨论 here , __finalize__ 无法跟踪作为数据框成员的系列,只能跟踪独立系列。因此,现在我将通过维护附加到数据帧的元数据字典来跟踪系列级元数据。我的代码如下所示:

def cust_merge(d1, d2):
    "Custom merge function for 2 dicts"
    ...

def finalize_df(self, other, method=None, **kwargs):
    for name in self._metadata:
        if method == 'merge':
            lmeta = getattr(other.left, name, {})
            rmeta = getattr(other.right, name, {})
            newmeta = cust_merge(lmeta, rmeta)
            object.__setattr__(self, name, newmeta)
        else:
            object.__setattr__(self, name, getattr(other, name, None))
    return self

df1.filenames = {c: 'fname1.csv' for c in df1}
df2.filenames = {c: 'fname2.csv' for c in df2}
pd.DataFrame._metadata = ['filenames']
pd.DataFrame.__finalize__ = finalize_df

最佳答案

我认为这样的事情会奏效(如果不行,请提交错误报告,虽然支持有点前沿,但 join 方法可能不会一直调用它。那就是有点未经测试)。

查看此 issue获取更详细的示例/错误修复。

DataFrame._metadata = ['name','filename']


def __finalize__(self, other, method=None, **kwargs):
    """
    propagate metadata from other to self

    Parameters
    ----------
    other : the object from which to get the attributes that we are going
        to propagate
    method : optional, a passed method name ; possibly to take different
        types of propagation actions based on this

    """

    ### you need to arbitrate when their are conflicts

    for name in self._metadata:
        object.__setattr__(self, name, getattr(other, name, None))
    return self

    DataFrame.__finalize__ = __finalize__

因此,这将用您的自定义终结器替换 DataFrame 的默认终结器。在我指出的地方,您需要放置一些可以在冲突之间进行仲裁的代码。这就是默认情况下不这样做的原因,例如frame1 的名称为“foo”,frame2 的名称为“bar”,当方法是 __add__ 时你会做什么,另一个方法呢?。让我们知道您做了什么以及结果如何。

这只是对 DataFrame 的替换(如果你愿意,你可以简单地执行默认操作),即将其他人传播给自己;你也可以不设置任何东西,除非在方法的特殊情况下。

这个方法是为了在子类中被覆盖,这就是为什么你在这里进行猴子修补(而不是子类化,这在大多数情况下是矫枉过正的)。

关于python - 通过连接传播 pandas 系列元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23200524/

相关文章:

python - bool 索引中列表理解的性能

Python-Matplotlib : plotting pivot table for hydrological year

asp.net-mvc - 单个 Asp.Net MVC 应用程序中的多个 .edmx

c# - 在没有 Visual Studio 的情况下以编程方式创建解决方案/项目

python - SQLAlchemy 通过 2 个多对多表建立关系

python - 关于Django的OneToOneField、ManyToManyField和ManyToOneField的解释

java - python import 相当于 Java 中的导入吗?

python - Pandas 蟒 : how to create multiple columns from a list

python - 连接系列中列表的元素

cocoa-touch - 将元数据写入图像时出现问题