python3 float转int_dataframe float转int

我首先要说的是,Pandas和NumPy数组的功能是从对数字数组进行高性能矢量化计算得出的。1向量化计算的全部目的是通过将计算移至高度优化的C代码并利用连续的内存块来避免Python级循环。2

Python级循环 现在我们来看一些时间。以下是所有的Python级环,其任一产生pd.Series,np.ndarray或list包含相同值的对象。为了分配给数据框内的序列,结果是可比较的。

Python 3.6.5, NumPy 1.14.3, Pandas 0.23.0

np.random.seed(0) N = 10**5

%timeit list(map(divide, df['A'], df['B'])) # 43.9 ms %timeit np.vectorize(divide)(df['A'], df['B']) # 48.1 ms %timeit [divide(a, b) for a, b in zip(df['A'], df['B'])] # 49.4 ms %timeit [divide(a, b) for a, b in df[['A', 'B']].itertuples(index=False)] # 112 ms %timeit df.apply(lambda row: divide(*row), axis=1, raw=True) # 760 ms %timeit df.apply(lambda row: divide(row['A'], row['B']), axis=1) # 4.83 s %timeit [divide(row['A'], row['B']) for _, row in df[['A', 'B']].iterrows()] # 11.6 s 一些要点:

的tuple基的方法(第一4)是一个因素比更有效的pd.Series基于方法(最后3)。 np.vectorize,列表理解+ zip和map方法(即前3名)的性能大致相同。这是因为它们使用tuple 并绕过了熊猫的开销pd.DataFrame.itertuples。 使用raw=Truewith pd.DataFrame.apply和不使用时,速度显着提高。此选项将NumPy数组而不是pd.Series对象提供给自定义函数。 pd.DataFrame.apply:只是另一个循环 要确切地查看Pandas传递的对象,可以对函数进行微不足道的修改:

def foo(row): print(type(row)) assert False # because you only need to see this once df.apply(lambda row: foo(row), axis=1) 输出:。相对于NumPy数组,创建,传递和查询Pandas系列对象会带来大量开销。这不足为奇:Pandas系列包含相当数量的脚手架,用于存放索引,值,属性等。

再次进行相同的练习raw=True,您会看到。所有这些都在文档中进行了描述,但是看到它更具说服力。

np.vectorize:假向量化 的文档np.vectorize有以下注意事项:

pyfunc除了使用numpy的广播规则外,矢量化函数像python map函数一样对输入数组的连续元组求值。

这里的“广播规则”是无关紧要的,因为输入数组具有相同的尺寸。与之并行map是有启发性的,因为上述map版本具有几乎相同的性能。该源代码显示发生的事情:np.vectorize你的输入函数转换成通用的功能通过(“ufunc”) np.frompyfunc。有一些优化,例如缓存,可以带来一些性能改进。

总之,np.vectorize做一个Python级环路什么应该做,但pd.DataFrame.apply增加了一个矮胖的开销。您不会看到任何JIT编译numba(请参见下文)。这只是一个方便。

真正的向量化:您应该使用什么 为什么在任何地方都没有提到上述差异?因为真正矢量化计算的性能使它们无关紧要:

%timeit np.where(df['B'] == 0, 0, df['A'] / df['B']) # 1.17 ms %timeit (df['A'] / df['B']).replace([np.inf, -np.inf], 0) # 1.96 ms 是的,这比上述循环式解决方案中最快的速度快40倍。这些都可以接受。在我看来,第一个是简洁,可读和高效的。numba如果性能至关重要,这只是瓶颈,请仅查看其他方法,例如下面的方法。

numba.njit:更高的效率 当循环被认为可行时,通常会通过numba底层的NumPy数组对其进行优化,以尽可能多地移至C。

实际上,将numba性能提高到了微秒。没有一些繁琐的工作,将很难获得比这更高的效率。

from numba import njit

@njit def divide(a, b): res = np.empty(a.shape) for i in range(len(a)): if b[i] != 0: res[i] = a[i] / b[i] else: res[i] = 0 return res

%timeit divide(df['A'].values, df['B'].values) # 717 µs 使用@njit(parallel=True)可以为更大的阵列提供进一步的提升。

1种数字类型包括:int,float,datetime,bool,category。它们不包含 object dtype,可以保存在连续的内存块中。

2 NumPy操作相对于Python高效的原因至少有两个:

Python中的所有内容都是一个对象。与C不同,这包括数字。因此,Python类型具有本机C类型不存在的开销。 NumPy方法通常基于C。另外,在可能的情况下使用优化算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值