【发布时间】:2017-07-21 20:16:49
【问题描述】:
我忽略了warnings 并尝试子类化 pandas DataFrame。我这样做的原因如下:
- 我想保留
DataFrame现有的所有方法。 - 我想在类实例化时设置一些额外的属性,稍后将用于定义我可以在子类上调用的额外方法。
这是一个sn-p:
class SubFrame(pd.DataFrame):
def __init__(self, *args, **kwargs):
freq = kwargs.pop('freq', None)
ddof = kwargs.pop('ddof', None)
super(SubFrame, self).__init__(*args, **kwargs)
self.freq = freq
self.ddof = ddof
self.index.freq = pd.tseries.frequencies.to_offset(self.freq)
@property
def _constructor(self):
return SubFrame
这是一个使用示例。假设我有DataFrame
print(df)
col0 col1 col2
2014-07-31 0.28393 1.84587 -1.37899
2014-08-31 5.71914 2.19755 3.97959
2014-09-30 -3.16015 -7.47063 -1.40869
2014-10-31 5.08850 1.14998 2.43273
2014-11-30 1.89474 -1.08953 2.67830
索引没有频率的地方
print(df.index)
DatetimeIndex(['2014-07-31', '2014-08-31', '2014-09-30', '2014-10-31',
'2014-11-30'],
dtype='datetime64[ns]', freq=None)
使用SubFrame 允许我一步指定频率:
sf = SubFrame(df, freq='M')
print(sf.index)
DatetimeIndex(['2014-07-31', '2014-08-31', '2014-09-30', '2014-10-31',
'2014-11-30'],
dtype='datetime64[ns]', freq='M')
问题是,这修改了df:
print(df.index.freq)
<MonthEnd>
这是怎么回事,我该如何避免这种情况?
此外,我自称使用了我不太了解的copied 代码。上面的__init__ 内发生了什么?有必要在这里使用带有pop 的args/kwargs 吗? (为什么我不能像往常一样指定参数?)
【问题讨论】:
-
子类化的典型用例是以某种方式修改/扩展基类功能。你不是真的在这里这样做。您只是以特定方式设置 DataFrame。您可能希望简单地创建一个工厂类型函数/对象,而不是子类,该函数/对象只是返回一个以您想要的方式构造的 DataFrame。对于这个特定的用例,子类化似乎没有多大意义。
-
“创建一个工厂类型的函数/对象,它只返回一个以你想要的方式构造的 DataFrame。”你能详细说明一下吗?现在我拥有的是一个标准的
Class(object),其中数据框是一个属性。是的,我通过定义多个其他方法来扩展功能,此处未显示。 -
看看 piRSquared 的第二个建议是用管道。注意他不是子类化。他正在创建一个函数,该函数仅以您希望的方式返回一个 DataFrame。没有必要子类化。你没有改变行为。工厂类的用途之一是以您想要的方式创建对象。如果您想在第一个副本的基础上创建一个新 DataFrame,您将创建一个函数,该函数将现有 DataFrame 作为参数,复制它,添加您的频率,然后返回副本。没有子类。
标签: python python-3.x pandas dataframe subclass