我对一个不可变的数据帧中的程序使用作为参考表,以READ_ONLY属性执行,它已初步构造之后(这在我的情况下是一个类def __init__()
方法期间)。
我看到索引对象被冻结。
有没有一种方法,使整个数据框不变?
尝试代码是这样的
class Bla(object):
def __init__(self):
self._df = pd.DataFrame(index=[1,2,3])
@property
def df(self):
return self._df.copy()
这将让你得到的DF回来,用b.df,但你不能够分配给它。因此,在短期你在课堂上DF,其行为在“不可改变的数据框”,纯粹是因为它块改动原。返回的对象是静止然而一个可变的数据帧,所以它不会表现得像一个不可变的一个在其他方面。即您将无法使用它作为密钥字典等
如果你忠实地想使DataFrame
表现为不可变的而不是使用@Joop的copy
解决方案(这我会建议),你可以建立在以下结构。
请注意,这只是一个起点。
它基本上是隐藏,将改变国家所有的东西,让自己被散列和相同的原始数据的所有实例将具有相同的哈希的代理数据对象。有可能是做下面的冷却器模块的方式,但我想它可能是教育作为一个例子。
一些警告:
DataFrame
s兼容。list
有一个特殊的情况下)。DataFrame
代理机辅助仅仅是一个开始,问题是,任何改变的原始对象的状态不能被允许或需要的方法来通过辅助手动覆盖或由extraFilter
参数实例_ReadOnly
当完全掩蔽英寸见DataFrameProxy.sort
。通用只读代理
这可以在任何物体上使用。
import md5
import warnings
class _ReadOnly(object):
def __init__(self, obj, extraFilter=tuple()):
self.__dict__['_obj'] = obj
self.__dict__['_d'] = None
self.__dict__['_extraFilter'] = extraFilter
self.__dict__['_hash'] = int(md5.md5(str(obj)).hexdigest(), 16)
@staticmethod
def _cloak(obj):
try:
hash(obj)
return obj
except TypeError:
return _ReadOnly(obj)
def __getitem__(self, value):
return _ReadOnly._cloak(self._obj[value])
def __setitem__(self, key, value):
raise TypeError(
"{0} has a _ReadOnly proxy around it".format(type(self._obj)))
def __delitem__(self, key):
raise TypeError(
"{0} has a _ReadOnly proxy around it".format(type(self._obj)))
def __getattr__(self, value):
if value in self.__dir__():
return _ReadOnly._cloak(getattr(self._obj, value))
elif value in dir(self._obj):
raise AttributeError("{0} attribute {1} is cloaked".format(
type(self._obj), value))
else:
raise AttributeError("{0} has no {1}".format(
type(self._obj), value))
def __setattr__(self, key, value):
raise TypeError(
"{0} has a _ReadOnly proxy around it".format(type(self._obj)))
def __delattr__(self, key):
raise TypeError(
"{0} has a _ReadOnly proxy around it".format(type(self._obj)))
def __dir__(self):
if self._d is None:
self.__dict__['_d'] = [
i for i in dir(self._obj) if not i.startswith('set')
and i not in self._extraFilter]
return self._d
def __repr__(self):
return self._obj.__repr__()
def __call__(self, *args, **kwargs):
if hasattr(self._obj, "__call__"):
return self._obj(*args, **kwargs)
else:
raise TypeError("{0} not callable".format(type(self._obj)))
def __hash__(self):
return self._hash
def __eq__(self, other):
try:
return hash(self) == hash(other)
except TypeError:
if isinstance(other, list):
try:
return all(zip(self, other))
except:
return False
return other == self
数据帧代理
真的应该有更多的方法,如sort
和过滤非利息收入的所有其他状态更改方法延长。
您可以用DataFrame
实例或者实例作为唯一参数,或给它的参数,你就必须创建一个DataFrame
import pandas as pd
class DataFrameProxy(_ReadOnly):
EXTRA_FILTER = ('drop', 'drop_duplicates', 'dropna')
def __init__(self, *args, **kwargs):
if (len(args) == 1 and
not len(kwargs) and
isinstance(args, pd.DataFrame)):
super(DataFrameProxy, self).__init__(args[0],
DataFrameProxy.EXTRA_FILTER)
else:
super(DataFrameProxy, self).__init__(pd.DataFrame(*args, **kwargs),
DataFrameProxy.EXTRA_FILTER)
def sort(self, inplace=False, *args, **kwargs):
if inplace:
warnings.warn("Inplace sorting overridden")
return self._obj.sort(*args, **kwargs)
最后:
然而,尽管乐趣使这个玩意儿,何不干脆都不要改变DataFrame
?如果只是暴露给你,更好的只是你要确保不改变它...
该StaticFrame包(其中我是作者),实现了熊猫一样的界面,和许多常见的熊猫操作,而强制执行标的与NumPy阵列和不可变系列和框架集装箱不变性。
你可以使整个大熊猫据帧不可改变通过与Frame
转换为StaticFrame static_frame.Frame.from_pandas(df)
。然后,你可以使用它作为一个真正的只读表。
见这个方法的StaticFrame文档:https://static-frame.readthedocs.io/en/latest/api_creation.html#static_frame.Series.from_pandas