是否有可能在应用了apply函数的对象的数据类型中工作?
据我了解,dtype已更改。

请参阅以下MWE。这个结果不是我想要达到的。

import pandas as pd
ds_a = pd.Series([True,False,True])
ds_b = ds_a.apply(lambda x: ~x)
print(ds_a.dtype == ds_b.dtype)
print(ds_b.dtype)


结果是:

False
int64


ds_b应该与ds_a具有相同的dtype(布尔值)。我对如何防止任何数据类型更改感兴趣。

编辑:这是我的用例更好的MWE。

请参阅以下(新的)MWE。

import pandas as pd
ds_a = pd.Series([True,False,True,True,True,False])
ds_mask = pd.Series([True,False])
func = lambda x: pd.np.all(x==ds_mask)
ds_b = ds_a.rolling(len(ds_mask)).apply(func, raw=True)
print(a(ds_a[:2]).dtype)
print(ds_b.dtype)


结果是:

dtype('bool')
float64

最佳答案

因此,问题不一定是DataFrame正在转换值。问题在于,与逻辑~运算符相反,正在使用按位补码运算符not。这导致TrueFalse的布尔值被视为整数,结果如下:

~True = -2
~False = -1


这就是导致输出DataFrame ds_b显示dtypeint64的原因。将代码更改为以下代码可以解决该问题。

import pandas as pd


ds_a = pd.Series([True,False,True])
ds_b = ds_a.apply(lambda x: not x)
print(ds_a.dtype == ds_b.dtype)
print(ds_b.dtype)


但是,您认为apply方法将根据输入来调整系列的类型是正确的。例如,在您的情况下,它将int转换为int64。如果您将来遇到这种行为并且不希望出现这种情况,请考虑以下代码。

ds_b = ds_a.apply(lambda x: ~x, convert_dtype=False).astype(ds_a.dtype)


这样可以防止apply进行自动转换,最后将dtypeobject转换为原始类型。这里有一些时间供您比较,它不会带来大量的开销。

In [26]: %timeit ds_b = ds_a.apply(lambda x: ~x)
257 µs ± 5.67 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [27]: %timeit ds_b = ds_a.apply(lambda x: ~x).astype(ds_a.dtype)
394 µs ± 23.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [28]: %timeit ds_b = ds_a.apply(lambda x: ~x, convert_dtype=False).astype(ds_
    ...: a.dtype)
359 µs ± 10.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


在您的最新示例中,Rolling实例自动尝试将数据作为float64处理。与使用Series或DataFrame rolling相比,使用apply有更多的限制。就目前而言,除了在最后转换结果之外,没有其他方法可以更改Pandas中滚动操作的数据类型。为此,我将看到上面用于强制转换dtype的代码,只是省略了convert_dtype对象的Rolling方法的apply参数,因为它不适用。

如果您愿意使用除Pandas以外的软件包,请a rolling function can be implemented using numpy。请参见以下代码:

import numpy as np

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

a = np.array([ True, False,  True,  True,  True, False])
mask = np.array([True, False])

b = (rolling_window(a, 2) == mask).all(axis=1, keepdims=True)


执行后,b等于第二个MVE的预期输出,但以numpy数组的形式出现。

array([[ True],
       [False],
       [False],
       [False],
       [ True]])

关于python - 如何防止.apply更改 boolean Pandas 系列的dtype,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58858744/

10-16 12:59