Pandas Cythonising熊猫:内容、索引和列的ctypes
我对Cython很陌生,但我已经经历了非凡的加速,只需将我的Pandas Cythonising熊猫:内容、索引和列的ctypes,pandas,cython,Pandas,Cython,我对Cython很陌生,但我已经经历了非凡的加速,只需将我的.py复制到.pyx(以及cimportCython,numpy等)并使用pyximport导入到ipython3。 许多教程从这种方法开始,下一步是为每种数据类型添加cdef声明,我可以在for循环等中为迭代器这样做。 但与大多数Pandas Cython教程或示例不同,我并没有应用函数,更多地使用切片、求和和和除法(等等)来处理数据 所以问题是:我是否可以通过声明我的数据帧只包含浮点(double),列为int,行为int,来提高代
.py
复制到.pyx
(以及cimportCython
,numpy
等)并使用pyximport
导入到ipython3
。
许多教程从这种方法开始,下一步是为每种数据类型添加cdef
声明,我可以在for循环等中为迭代器这样做。
但与大多数Pandas Cython教程或示例不同,我并没有应用函数,更多地使用切片、求和和和除法(等等)来处理数据
所以问题是:我是否可以通过声明我的数据帧只包含浮点(double
),列为int
,行为int
,来提高代码的运行速度
如何定义嵌入列表的类型?i、 e[[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
我的建议是在熊猫身上尽可能地做。这是一个标准的建议“先让它工作起来,如果它真的很重要,那么就关注性能”。因此,让我们假设您已经完成了(希望您也编写了一些测试),但是速度太慢了: 分析代码。(请参阅或在ipython中使用%prun) prun的输出应该驱动下一步改进的位
将整个代码放入cython实际上不会有多大帮助,您只需要放入对性能敏感的特定行或函数调用。保持cython专注是享受美好时光的唯一方法 请阅读*!在这里,这个过程(prun->cythonize->type)通过一个实际示例一步一步地介绍
*完全公开我写的那部分文档!:) 把我的全部代码都放到Cython中,真是帮了大忙!从隔夜跑步到20分钟!!观察CPU状态,在Python中运行时,CPU在C1+中花费了大量时间。因此,受此驱动,问题更多的是“如何获得全面加速”,而不是优化。感谢您的文档和其他工作,这是我取得成就的基础。Pandas会处理所有的单元类型并将其传递给cython吗?嗯,可能会,但我认为只需cython化一小部分代码(性能敏感位),就可以获得更有效的加速。当您使用Pandas方法时,Pandas确实会处理不同的数据类型(这些方法已经矢量化或用cython本身编写)。也就是说,作为对“如何获得整体加速而不是优化”的回应,您应该能够从优化中获得比整体加速更多的加速。