python/pandas: 当 'inplace' 不可能时,DataFrame 继承和 DataFrame 更新
python/pandas: DataFrame inheritance and DataFrame update when 'inplace' is not possible
对不起,我知道标题有点模糊。
上下文
我正在使用 Dataframe
来跟踪文件,因为 pandas DataFrame
具有几个相关功能来执行字典无法执行的所有类型的过滤, loc
, pd.IndexSlice
, .index
, .columns
, pd.MultiIndex
...
好吧,这可能不是专业开发人员的最佳选择(我不是),但所有这些功能都非常方便,我已经开始使用 DataFrame
来实现这一点。
蛋糕上的樱桃,MultiIndex Dataframe
的 __repr__
当我想知道我的文件列表中有什么时,它是完美的。
Summary
class 的快速介绍,继承自 DataFrame
因为我的DataFrame
,我叫'Summary',有一些特定的功能,我想把它做成class,继承自pandas DataFrame
class。
它还具有 'fixed' MultiIndexes,用于行和列。
最后,因为我的Summary
class是在Store
class之外定义的,它实际上是管理文件组织,Summary
class需要 Store
中的函数才能检索文件组织。
问题
pd.DataFrame
的问题是(据我所知)您不能在不创建新的 DataFrame
的情况下追加行。
由于 Summary
具有 refresh
功能,因此它可以通过读取文件夹内容来 recreate
自身, refresh
以某种方式 'reset' 'Summary' object.
为了管理 Summary
刷新,我想出了第一个代码(不工作),最后是第二个(工作)。
import pandas as pd
import numpy as np
# Dummy function
def summa(a,b):
return a+b
# Does not work
class DatF1(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = pd.MultiIndex.from_arrays([['Comp1','Comp1'],['1h','1W']],names=['Component','Interval'])
self = pd.DataFrame(values, index=rmidx, columns=self.columns)
ex1 = DatF1(summa)
In [10]: ex1.meth(3,4)
Out[10]: 7
ex1.refresh()
In [11]: ex1
Out[11]: Empty DatF1
Columns: [(Index, First), (Index, Last)]
Index: []
refresh()
之后,ex1
还是空的。 refresh
工作不正常。
# Works
class DatF2(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = pd.MultiIndex.from_arrays([['Comp1','Comp1'],['1h','1W']],names=['Component','Interval'])
super().__init__(values, index=rmidx, columns=self.columns)
ex2 = DatF2(summa)
In [10]: ex2.meth(3,4)
Out[10]: 7
ex2.refresh()
In [11]: ex2
Out[11]: Index
First Last
Component Interval
Comp1 1h 2020-02-10 08:00:00 2020-02-10 08:00:00
1W 2020-02-11 08:00:00 2020-02-12 08:00:00
此代码有效!
我有两个问题:
为什么第一个代码不起作用? (对不起,这可能是显而易见的,但我完全不知道为什么它不起作用)
在我的 refresh
方法中调用 super().__init__
可接受的编码实践? (或换句话说:在我的子 class 的 __init__
之外的其他地方调用 super().__init__
是否可以接受?)
非常感谢您的帮助和建议。 class 继承的世界对我来说很新鲜,而且 DataFrame
内容不能直接修改,这么说,在我看来似乎更难处理。
祝你有美好的一天,
最佳,
添加新行时出现错误消息
import pandas as pd
import numpy as np
# Dummy function
def new_rows():
return [['Comp1','Comp1'],['1h','1W']]
# Does not work
class DatF1(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = self.meth()
self[rmidx] = values
ex1 = DatF1(new_rows)
ex1.refresh()
KeyError: "None of [MultiIndex([('Comp1', 'Comp1'),\n ( '1h', '1W')],\n names=['Component', 'Interval'])] are in the [index]"
您问题的答案
why the 1st code is not working?
您正在尝试调用您继承自的 class。老实说,我不知道你的情况到底发生了什么。我以为这会产生错误,但你得到的是一个空数据框。
is calling super().__init__
in my refresh method acceptable coding practise?
可能存在在 __init__() 方法之外调用 super().__init__
的合法用例。但你的情况不是其中之一。您已经从 __init__() 中继承了一切。为什么要再次使用它?
更好的解决方案
解决你的问题出乎意料的简单。因为你可以 append a row to a Dataframe:
df['new_row'] = [value_1, value_2, ...]
或者在您使用 MultiIndex 的情况下(参见 this SO post):
df.loc[('1h', '1W'), :] = [pd.Timestamp('2020/02/10 8:00'), pd.Timestamp('2020/02/10 8:00')]
最佳实践
您不应该继承自 pd.DataFrame。如果你想扩展 pandas 使用 documented API.
对不起,我知道标题有点模糊。
上下文
我正在使用 Dataframe
来跟踪文件,因为 pandas DataFrame
具有几个相关功能来执行字典无法执行的所有类型的过滤, loc
, pd.IndexSlice
, .index
, .columns
, pd.MultiIndex
...
好吧,这可能不是专业开发人员的最佳选择(我不是),但所有这些功能都非常方便,我已经开始使用 DataFrame
来实现这一点。
蛋糕上的樱桃,MultiIndex Dataframe
的 __repr__
当我想知道我的文件列表中有什么时,它是完美的。
Summary
class 的快速介绍,继承自 DataFrame
因为我的DataFrame
,我叫'Summary',有一些特定的功能,我想把它做成class,继承自pandas DataFrame
class。
它还具有 'fixed' MultiIndexes,用于行和列。
最后,因为我的Summary
class是在Store
class之外定义的,它实际上是管理文件组织,Summary
class需要 Store
中的函数才能检索文件组织。
问题
pd.DataFrame
的问题是(据我所知)您不能在不创建新的 DataFrame
的情况下追加行。
由于 Summary
具有 refresh
功能,因此它可以通过读取文件夹内容来 recreate
自身, refresh
以某种方式 'reset' 'Summary' object.
为了管理 Summary
刷新,我想出了第一个代码(不工作),最后是第二个(工作)。
import pandas as pd
import numpy as np
# Dummy function
def summa(a,b):
return a+b
# Does not work
class DatF1(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = pd.MultiIndex.from_arrays([['Comp1','Comp1'],['1h','1W']],names=['Component','Interval'])
self = pd.DataFrame(values, index=rmidx, columns=self.columns)
ex1 = DatF1(summa)
In [10]: ex1.meth(3,4)
Out[10]: 7
ex1.refresh()
In [11]: ex1
Out[11]: Empty DatF1
Columns: [(Index, First), (Index, Last)]
Index: []
refresh()
之后,ex1
还是空的。 refresh
工作不正常。
# Works
class DatF2(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = pd.MultiIndex.from_arrays([['Comp1','Comp1'],['1h','1W']],names=['Component','Interval'])
super().__init__(values, index=rmidx, columns=self.columns)
ex2 = DatF2(summa)
In [10]: ex2.meth(3,4)
Out[10]: 7
ex2.refresh()
In [11]: ex2
Out[11]: Index
First Last
Component Interval
Comp1 1h 2020-02-10 08:00:00 2020-02-10 08:00:00
1W 2020-02-11 08:00:00 2020-02-12 08:00:00
此代码有效!
我有两个问题:
为什么第一个代码不起作用? (对不起,这可能是显而易见的,但我完全不知道为什么它不起作用)
在我的
refresh
方法中调用super().__init__
可接受的编码实践? (或换句话说:在我的子 class 的__init__
之外的其他地方调用super().__init__
是否可以接受?)
非常感谢您的帮助和建议。 class 继承的世界对我来说很新鲜,而且 DataFrame
内容不能直接修改,这么说,在我看来似乎更难处理。
祝你有美好的一天, 最佳,
添加新行时出现错误消息
import pandas as pd
import numpy as np
# Dummy function
def new_rows():
return [['Comp1','Comp1'],['1h','1W']]
# Does not work
class DatF1(pd.DataFrame):
def __init__(self,meth,data=None):
cmidx = pd.MultiIndex.from_arrays([['Index', 'Index'],['First', 'Last']])
rmidx = pd.MultiIndex(levels=[[],[]], codes=[[],[]],
names=['Component','Interval'])
super().__init__(data=data, index=rmidx, columns=cmidx, dtype=np.datetime64)
self.meth=meth
def refresh(self):
values = [[pd.Timestamp('2020/02/10 8:00'),pd.Timestamp('2020/02/10 8:00')],
[pd.Timestamp('2020/02/11 8:00'),pd.Timestamp('2020/02/12 8:00')]]
rmidx = self.meth()
self[rmidx] = values
ex1 = DatF1(new_rows)
ex1.refresh()
KeyError: "None of [MultiIndex([('Comp1', 'Comp1'),\n ( '1h', '1W')],\n names=['Component', 'Interval'])] are in the [index]"
您问题的答案
why the 1st code is not working?
您正在尝试调用您继承自的 class。老实说,我不知道你的情况到底发生了什么。我以为这会产生错误,但你得到的是一个空数据框。
is calling
super().__init__
in my refresh method acceptable coding practise?
可能存在在 __init__() 方法之外调用 super().__init__
的合法用例。但你的情况不是其中之一。您已经从 __init__() 中继承了一切。为什么要再次使用它?
更好的解决方案
解决你的问题出乎意料的简单。因为你可以 append a row to a Dataframe:
df['new_row'] = [value_1, value_2, ...]
或者在您使用 MultiIndex 的情况下(参见 this SO post):
df.loc[('1h', '1W'), :] = [pd.Timestamp('2020/02/10 8:00'), pd.Timestamp('2020/02/10 8:00')]
最佳实践
您不应该继承自 pd.DataFrame。如果你想扩展 pandas 使用 documented API.