python - 是否有一个 pandas 访问器来存储每个单元格中对象的底层值?

标签 python pandas object accessor

在代码库中,我有包含自定义对象的 pandas 对象 (pd.DataFrame/pd.Series)。

如果我可以从底层对象调用方法或属性而无需求助于 .apply,这将显着简化代码库。

为了说明这一点,请考虑 pandas 系列的“汽车”对象。

class Car:
   ...
   def max_speed(self)->float:
      ...

x = pd.Series([car1, car2, car3]) 

目前我可以通过以下方式获得平均车速:

x.apply(lambda x: x.max_speed()).mean()

我认为如果我可以跳过 .apply(lambda x: x...) 并将其替换为以下内容,那就太好了:

x.obj.max_speed().mean()

其中 obj 是我的自定义访问器。

为了进一步说明这一点,请考虑一个类 Plane

class Plane:
    def cruise_height(self)->float:

在我的代码库中:

x1 = pd.Series([car1, car2, car3])
x2 = pd.Series([plane1, plane2, plane3])

我可以得到平均汽车速度/飞机巡航高度

x1.apply(lambda x: x.max_speed()).mean()
x2.apply(lambda x: x.cruise_height()).mean()

我认为如果我可以这样做,它会更具可读性:

x1.obj.max_speed().mean()
x2.obj.cruise_height().mean()

我想这与 .str. 公开底层字符串方法的方式类似。

pd.Series(['Hello', 'World']).str.get(0) # returns ['H', 'W']
pd.Series(['Hello', 'World']).str.upper()
# etc

最佳答案

根据 Pandas 文档,您可以注册 custom accessors使用特殊的装饰器,如下所示:

import pandas as pd

@pd.api.extensions.register_series_accessor("spec")
class SpecAccessor:
    def __init__(self, pandas_obj: pd.Series):
        self._obj = pandas_obj
        for i in range(len(self._obj)):
            for attr in self._obj[i].__class__.__dict__:
                # set objects methods on the accessor
                if not attr.startswith("__"):
                    ser = pd.Series(
                        [getattr(self._obj[i], attr)() for i in range(len(self._obj))]
                    )
                    setattr(self, attr, ser)

因此,使用以下类和实例:

class Car:
    def __init__(self, speed: float):
        self._speed = speed

    def max_speed(self) -> float:
        return self._speed * 1.5

class Plane:
    def __init__(self, max_height: float):
        self._max_height = max_height

    def cruise_height(self) -> float:
        return self._max_height * 0.6

car1 = Car(10.0)
car2 = Car(30.5)
car3 = Car(50.9)

plane1 = Plane(5_000.0)
plane2 = Plane(3_000.5)
plane3 = Plane(9_000.9)

你可以这样做:

print(pd.Series([car1, car2, car3]).spec.max_speed)
# Ouputs
0    15.00
1    45.75
2    76.35
dtype: float64

print(pd.Series([plane1, plane2, plane3]).spec.cruise_height)
# Outputs
0    3000.00
1    1800.30
2    5400.54
dtype: float64

关于python - 是否有一个 pandas 访问器来存储每个单元格中对象的底层值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70609935/

相关文章:

javascript - 显示给定输入数字的数据集中所有可能的字母组合

python - django shell 未检测到新模块

python - 关系 "hello_greeting"不存在

python - 使用 Python 的 map 进行逻辑索引

python - 在Anaconda中播放文件中的视频

python - 连续开关信号之间的行数

python - 从 pandas df 中选择特定列

javascript - 将 Javascript 序列化转换为 Javascript 对象

python - 值错误: time data '10/11/2006 24:00' does not match format '%d/%m/%Y %H:%M'

java - printf 不适用于字符串