io sono molto nuovo a Cython, ma sto già sperimentando incrementi nella velocità straordinarie semplicemente copiando il mio .py
-.pyx
(e cimport cython
, numpy
ecc) e l'importazione in ipython3
con pyximport
. Molti approcci iniziano con questo approccio e il passo successivo consiste nell'aggiungere le dichiarazioni cdef
per ogni tipo di dati, che posso fare per gli iteratori nei miei cicli for ecc. Ma diversamente dalla maggior parte dei tutorial o degli esempi di Pandas Cython, non sono applicabile le funzioni per parla, manipola più dati usando slice, somme e divisioni (etc).Cythonising Pandas: ctypes per i contenuti, indice e colonne
Quindi la domanda è: Posso aumentare la velocità con cui il mio codice viene eseguito, affermando che la mia dataframe contiene solo carri (double
), con colonne che sono int
e le righe che sono int
?
Come definire il tipo di un elenco incorporato? cioè [[int,int],[int]]
Ecco un esempio che genera il punteggio AIC per un partizionamento di un DF, mi dispiace è così dettagliata:
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
Inserire tutto il codice in Cython ha aiutato incredibilmente!Da una corsa notturna a 20 minuti !! Guardando gli stati della CPU, quando si eseguiva in Python la CPU passava molto tempo in C1 +. Così motivato da questo, la domanda è più di un "come ottenere aumenti di velocità" piuttosto che l'ottimizzazione. Grazie per i documenti e altri lavori che stai facendo, è stata la base per arrivare fino a 8). Panda gestisce tutti i tipi di celle e lo trasmette a cython? – SpmP
Beh, potrebbe darsi, ma penso che si possa ottenere una maggiore efficacia accelerando solo la cythonizzazione di una piccola parte del codice (il bit sensibile alle prestazioni). Pandas gestisce diversi tipi di dtype quando si usano i metodi pandas (questi sono già vecorizzati o scritti in cython). –
Vale a dire, in risposta a "" come ottenere aumenti di velocità "piuttosto che ottimizzazione", dovresti essere in grado di ottenere * più * accelerazioni dall'ottimizzazione rispetto alla cythonizzazione globale. –