在Pandas中,我一直使用自定义对象作为列标签,因为它们为特定于列的信息/方法提供了丰富/灵活的功能。例如,您可以设置自定义fmt_fn
来格式化每一列(请注意,这只是一个示例,我的实际列标签对象更复杂):
In [100]: class Col:
...: def __init__(self, name, fmt_fn):
...: self.name = name
...: self.fmt_fn = fmt_fn
...: def __str__(self):
...: return self.name
...:
In [101]: sec_col = Col('time', lambda val: str(timedelta(seconds=val)).split('.')[0])
In [102]: dollar_col = Col('money', lambda val: '${:.2f}'.format(val))
In [103]: foo = pd.DataFrame(np.random.random((3, 2)) * 1000, columns = [sec_col, dollar_col])
In [104]: print(foo) # ugly
time money
0 773.181402 720.997051
1 33.779925 317.957813
2 590.750129 416.293245
In [105]: print(foo.to_string(formatters = [col.fmt_fn for col in foo.columns])) # pretty
time money
0 0:12:53 $721.00
1 0:00:33 $317.96
2 0:09:50 $416.29
好的,所以我很乐意这样做一段时间,但后来我最近遇到了一部分不支持这种情况的Pandas。具体而言,具有自定义列标签的DataFrame上的方法to_hdf
/ read_hdf
will fail。这对我来说不是一个破坏者。我可以使用泡菜而不是HDF5而失去一些效率。
但更大的问题是,Pandas一般是否支持自定义对象作为列标签?换句话说,我应该继续以这种方式使用Pandas,还是将来会在Pandas的其他部分(除了HDF5)中断,这会让我后来感到痛苦?
PS。作为旁注,如果您当前没有使用自定义对象作为列,我也不介意您是否也在讨论如何解决列特定信息的问题,例如上例中的fmt_fn
标签。
答案 0 :(得分:0)
现在,DataFrame
格式化的细粒度控制真的不可能。例如,有关可能性的讨论,请参见here或here。我确信一个经过深思熟虑的API(和PR!)会很受欢迎。
在将自定义对象用作列时,两个最大的问题可能是序列化和索引语义(例如,不能再进行df['time']
)。
一种可能的解决方法是将DataFrame
包装成某种漂亮的印刷结构,如下所示:
In [174]: class PrettyDF(object):
...: def __init__(self, data, formatters):
...: self.data = data
...: self.formatters = formatters
...: def __str__(self):
...: return self.data.to_string(formatters=self.formatters)
...: def __repr__(self):
...: return self.__str__()
In [172]: foo = PrettyDF(df,
formatters={'money': '${:.2f}'.format,
'time': lambda val: str(timedelta(seconds=val)).split('.')[0]})
In [178]: foo
Out[178]:
time money
0 0:13:17 $399.29
1 0:08:48 $122.44
2 0:07:42 $491.72
In [180]: foo.data['time']
Out[180]:
0 797.699511
1 528.155876
2 462.999224
Name: time, dtype: float64
答案 1 :(得分:0)
自发布以来已经有五年了,所以我希望这对某人还是有帮助的。我设法建立了一个对象来保存pandas数据框列的元数据,但仍然可以作为常规列访问(对我来说似乎如此)。下面的代码只是涉及此内容的整个类的一部分。
__ repr用于在打印数据框而不是对象时显示对象的名称
__ eq用于将请求的名称检查为对象的可用名称__hash在此过程中也被使用,因为列名的工作方式类似于字典,所以它们必须是可哈希的。
那可能不是描述它的Python方式,但在我看来,这就是它的工作方式。
class ColumnDescriptor:
def __init__(self, name, **kwargs):
self.name = name
[self.__setattr__(n, v) for n, v in kwargs.items()]
def __repr__(self): return self.name
def __str__(self): return self.name
def __eq__(self, other): return self.name == other
def __hash__(self): return hash(self.name)