gpt4 book ai didi

pandas - Pandas Series 界面不一致;产生对底层数据的访问

转载 作者:行者123 更新时间:2023-12-01 12:38:00 30 4
gpt4 key购买 nike

虽然自 pandas 0.15.0 以来新的分类系列支持非常棒,但我对他们如何决定让基础数据无法访问(除非通过带下划线的变量)感到有点恼火。考虑以下代码:

import numpy as np
import pandas as pd

x = np.empty(3, dtype=np.int64)

s = pd.DatetimeIndex(x, tz='UTC')

x
Out[17]: array([140556737562568, 55872352, 32])

s[0]
Out[18]: Timestamp('1970-01-02 15:02:36.737562568+0000', tz='UTC')

x[0] = 0

s[0]
Out[20]: Timestamp('1970-01-01 00:00:00+0000', tz='UTC')

y = s.values

y[0] = 5

x[0]
Out[23]: 5

s[0]
Out[24]: Timestamp('1970-01-01 00:00:00.000000005+0000', tz='UTC')

我们可以看到,无论是在构造中还是在询问基础值时,都没有在这个 DatetimeIndex 中对其基础数据进行深拷贝。这不仅在效率方面可能有用,而且如果您使用 DataFrame 作为缓冲区,这也很棒。您可以轻松获取包含底层数据的 numpy 基元,从那里获取指向原始数据的指针,一些低级 C 例程可以使用它从某个内存块复制到其中。

现在让我们看看新分类系列的行为。底层数据当然不是级别,而是代码。

x2 = np.zeros(3, dtype=np.int64)

s2 = pd.Categorical.from_codes(x2, ["hello", "bye"])

s2
Out[27]:
[hello, hello, hello]
Categories (2, object): [hello, bye]

x2[0] = 1

s2[0]
Out[29]: 'hello'

y2 = s2.codes

y2[0] = 1
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-31-0366d645c98d> in <module>()
----> 1 y2[0] = 1

ValueError: assignment destination is read-only

y2 = s2._codes

y2[0] = 1

s2[0]
Out[34]: 'bye'

此行为的最终结果是,作为开发人员,对分类的基础数据的有效操作不是接口(interface)的一部分。同样作为用户, from_codes 构造函数很慢,因为它深度复制代码,这通常是不必要的。至少应该有一个选项。

但是 codes 是一个只读变量并且需要使用 _codes 的事实让我觉得更糟。为什么 .codes 不会给出与 .values 相同的行为?除了代码是“私有(private)”的概念之外,是否还有其他理由可以证明这一点?我希望 stackoverflow 上的一些 pandas 专家可以对此有所启发。

最佳答案

Categorical 类型与几乎所有其他类型的不同之处在于它是一种复合类型,在其数据之间具有一定的保证。也就是说,代码提供了级别的因式分解。

所以反对可变性的论点是,它很容易破坏代码-类别映射,而且可能性能不佳。当然,可以通过检查 setitem 来减轻这些问题(但会增加一些代码复杂性)。

绝大多数用户不会直接操作代码/类别(并且只会使用暴露的方法),因此这确实是一种防止意外破坏这些保证的保护措施。

如果您需要有效地操作底层数据,最好/最简单的方法就是提取代码/类别。改变它们,然后创建一个新的分类(如果已经提供了代码/类别,这很便宜)。

例如

In [3]: s2 = pd.Categorical.from_codes(x2, ["hello", "bye"])

In [4]: s2
Out[4]:
[hello, hello, hello]
Categories (2, object): [hello, bye]

In [5]: s2.codes
Out[5]: array([0, 0, 0], dtype=int8)

In [6]: pd.Categorical(s2.codes+1,s2.categories,fastpath=True)
Out[6]:
[bye, bye, bye]
Categories (2, object): [hello, bye]

当然这很危险,如果你在表达式中加 2 就会爆炸。直接操作代码只是买家当心。

关于pandas - Pandas Series 界面不一致;产生对底层数据的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27829294/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com