gpt4 book ai didi

python - 将修饰的 DataFrame 与所有 pandas 函数关联

转载 作者:行者123 更新时间:2023-12-01 04:45:36 24 4
gpt4 key购买 nike

我想向我的 DataFrame 添加一个唯一的 id,通过使用我在这里找到的内容,我基本上成功了,Python Class Decorator 。我从这里知道https://github.com/pydata/pandas/issues/2485尚未明确支持添加自定义元数据,但装饰器似乎是一种解决方法。

当我使用 copy 和 groupby.agg 等方法时,我的装饰 DataFrame 返回新的且类似装饰的 DataFrame。如何让“所有”pandas 函数(例如 pd.DataFrame() 或 pd.read_csv)返回经过修饰的 DataFrame,而不是原始的、未修饰的 DataFrame,而无需单独修饰每个 pandas 函数?即,如何让我的装饰 DataFrame 替换库存 DataFrame?

这是我的代码。首先,我有一个增强的 pandas 模块,wrapPandas.py。

from pandas import *
import numpy as np

def addId(cls):

class withId(cls):

def __init__(self, *args, **kargs):
super(withId, self).__init__(*args, **kargs)
self._myId = np.random.randint(0,99999)

return withId

pandas.core.frame.DataFrame = addId(pandas.core.frame.DataFrame)

运行以下代码片段显示,当我使用 .copy() 和 .groupby().agg() 等方法时,我的 DataFrame 返回修饰的 DataFrame。然后,我将通过展示 pd.DataFrame 等 pandas 函数不会返回我的装饰 DataFrame(遗憾的是,但并不奇怪)来跟进。

编辑:根据 Jonathan Eunice 的回复添加了导入语句。

import wrapPandas as pd

d = {
'strCol': ['A', 'B', 'A', 'C', 'B', 'B', 'A', 'C', 'A'],
'intCol': [6,3,8,6,7,3,9,2,6],
}

#create "decorated" DataFrame
dfFoo = pd.core.frame.DataFrame.from_records(d)
print("dfFoo._myId = {}".format(dfFoo._myId))

#new DataFrame with new ._myId
dfBat = dfFoo.copy()
print("dfBat._myId = {}".format(dfBat._myId))

#new binding for old DataFrame, keeps old ._myId
dfRat = dfFoo
print("dfRat._myId = {}".format(dfRat._myId))

#new DataFrame with new ._myId
dfBird = dfFoo.groupby('strCol').agg({'intCol': 'sum'})
print("dfBird._myId = {}".format(dfBird._myId))

#all of these new DataFrames have the same type, "withId"
print("type(dfFoo) = {}".format(type(dfFoo)))

这会产生以下结果。

dfFoo._myId = 66622
dfBat._myId = 22527
dfRat._myId = 66622
dfBird._myId = 97593
type(dfFoo) = <class 'wrapPandas.withId'>

还有令人悲伤的部分。 dfBoo._myId 当然会引发 AttributeError

#create "stock" DataFrame
dfBoo = pd.DataFrame(d)
print(type(dfBoo))

#doesn't have a ._myId (I wish it did, though)
print(dfBoo._myId)

最佳答案

将您的猴子补丁修改为:

pd.DataFrame = pandas.core.frame.DataFrame = addId(pandas.core.frame.DataFrame)

即所以你正在“锁定”或“猴子修补”两个不同的名称。考虑到 pandas.core.frame.DataFrame 是 pd.DataFrame,这种双重分配的需要可能看起来很奇怪。但您实际上并没有修改 DataFrame 类。您正在注入(inject)一个代理类。无论对代理的引用如何,都有效。直接到原始类的那些没有获得代理行为。通过将您可能想要使用的所有名称都指向代理来更改这一点。下面是它看起来更直观的样子:

diagram

我假设您的文件中的某处还有一个 import pandas as pd ,但未显示,否则您的 dfBoo 定义将失败,并出现 NameError: name ' pd' 未定义

由于这样的原因,猴子修补是危险的。你正在注入(inject)东西......并且不可能知道你是否“捕获了所有引用”或“修补了你需要的所有内容”。我不能保证代码中不会有其他调用来处理比此名称更低级别的结构,重新调整不会生效。但对于显示的代码来说,它是有效的!

更新您后来询问了如何使此功能适用于pd.read_csv。嗯,这是您可能需要修补的另一个地方。此时,将上面的补丁代码修改为:

pd.DataFrame = pandas.io.parsers.DataFrame = pandas.core.frame.DataFrame = addId(pandas.core.frame.DataFrame)

修补 pandas.io.parsers.DataFrameDataFrame 的定义可以解决 read_csv 的问题。同样的警告也适用:您可能需要追踪更多用途才能完全覆盖。

关于python - 将修饰的 DataFrame 与所有 pandas 函数关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29474644/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com