是否有可能在应用了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
。这导致True
和False
的布尔值被视为整数,结果如下:
~True = -2
~False = -1
这就是导致输出DataFrame
ds_b
显示dtype
为int64
的原因。将代码更改为以下代码可以解决该问题。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
进行自动转换,最后将dtype
从object
转换为原始类型。这里有一些时间供您比较,它不会带来大量的开销。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/