是否有可能在应用了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
答案 0 :(得分:2)
因此,问题不一定是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
的{{1}}从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]])
答案 1 :(得分:0)
只需将显式转换添加到您要应用的boolean
中的lambda
import pandas as pd
ds_a = pd.Series([True,False,True])
ds_b = ds_a.apply(lambda x: bool(~x))
print(ds_a.dtype == ds_b.dtype)
print(ds_b.dtype)