我是很新的,以用Cython,但我已经经历了非凡的加速只复制我.py来.pyx(和cimport cython,numpy等等),并导入到ipython3用pyximport.许多教程都是从这种方法开始的,下一步是cdef为每个数据类型添加声明,我可以为for循环中的迭代器做.但与大多数Pandas Cython教程或示例不同,我不应用函数,可以这么说,更多使用切片,求和和(等)来操纵数据.
所以问题是:我可以通过声明我的DataFrame只包含floats(double),并且列是int行和行来增加代码运行的速度int吗?
如何定义嵌入列表的类型?即[[int,int],[int]]
这是一个为DF分区生成AIC分数的示例,对不起它是如此冗长:
cimport cython
import numpy as np
cimport numpy as np
import pandas as pd
offcat = [
"breakingPeace",
"damage",
"deception",
"kill",
"miscellaneous",
"royalOffences",
"sexual",
"theft",
"violentTheft"
]
def partitionAIC(EmpFrame, part, OffenceEstimateFrame, ReturnDeathEstimate=False):
"""EmpFrame is DataFrame of ints, part is nested list of ints, OffenceEstimate frame is DF of float"""
"""partOf/block is a list of ints"""
"""ll, AIC, is series/frame of floats"""
##Cython cdefs
cdef int DFlen
cdef int puns
cdef int DeathPun
cdef int k
cdef int pId
cdef int punish
DFlen = EmpFrame.shape[1]
puns = 2
DeathPun = 0
PartitionModel = pd.DataFrame(index = EmpFrame.index, columns = EmpFrame.columns)
for partOf in part:
Grouping = [puns*x + y for x in partOf for y in list(range(0,puns))]
PartGroupSum = EmpFrame.iloc[:,Grouping].sum(axis=1)
for punish in range(0,puns):
PunishGroup = [x*puns+punish for x in partOf]
punishPunishment = ((EmpFrame.iloc[:,PunishGroup].sum(axis = 1) + 1/puns).div(PartGroupSum+1)).values[np.newaxis].T
PartitionModel.iloc[:,PunishGroup] = punishPunishment
PartitionModel = PartitionModel*OffenceEstimateFrame
if ReturnDeathEstimate:
DeathProbFrame = pd.DataFrame([[part]], index=EmpFrame.index, columns=['Partition'])
for pId,block in enumerate(part):
DeathProbFrame[pId] = PartitionModel.iloc[:,block[::puns]].sum(axis=1)
DeathProbFrame = DeathProbFrame.apply(lambda row: sorted( [ [format("%6.5f"%row[idx])]+[offcat[X] for X in x ]
for idx,x in enumerate(row['Partition'])],
key=lambda x: x[0], reverse=True),axis=1)
ll = (EmpFrame*np.log(PartitionModel.convert_objects(convert_numeric=True))).sum(axis=1)
k = (len(part))*(puns-1)
AIC = 2*k-2*ll
if ReturnDeathEstimate:
return AIC, DeathProbFrame
else:
return AIC
Run Code Online (Sandbox Code Playgroud)
我的建议是尽可能多地做大熊猫.这是一种标准的建议"让它先工作,然后关注性能,如果真的很重要".所以让我们假设你已经完成了(希望你也写了一些测试),而且它太慢了:
描述您的代码.(请参阅此SO答案,或在ipython中使用%prun).
prun的输出应该驱动接下来要改进的位.
现在,如果它是一个与切片相关的线(可能不是)将这个小部分放在cython中,我喜欢删除对cython函数的单个python函数调用.在这一点上cython的东西应该使用numpy而不是pandas,我不认为pandas不会降低到C(cython不能推断类型).
将整个代码放入cython实际上并没有多大帮助,你只想放置对性能敏感的特定行或函数调用.保持cython聚焦是获得美好时光的唯一方法.
阅读pandas docs*的增强性能部分!这个过程(prun - > cythonize - > type)通过一个真实的例子逐步完成.
*完全透露我写的那部分文档!:)
| 归档时间: |
|
| 查看次数: |
2412 次 |
| 最近记录: |