2015-04-25 8 views
5

Ich bin sehr neu Cython, noch erlebe schon außergewöhnliche speedups nur kopieren meine .py-.pyx (und cimport cython, numpy usw.) und den Import in ipython3 mit pyximport. Viele Tutorials beginnen in diesem Ansatz mit dem nächsten Schritt, cdef Deklarationen für jeden Datentyp hinzuzufügen, was ich für die Iteratoren in meinen for-Schleifen usw. tun kann. Aber im Gegensatz zu den meisten Pandas Cython Tutorials oder Beispielen bin ich keine Funktionen so zu speak, mehr Daten manipulieren mit Scheiben, Summen und Division (etc).Cythonising Pandas: ctypes für Inhalt, Index und Spalten

So ist die Frage: Kann ich die Geschwindigkeit erhöhen, mit der mein Code ausgeführt werden mit der Feststellung, dass mein Datenrahmen schwebt nur enthält (double), mit Spalten, die int und Zeilen sind, die int sind?

Wie definiere ich den Typ einer eingebetteten Liste? d.h [[int,int],[int]]

Hier ist ein Beispiel, das das AIC-Score für eine Aufteilung eines DF erzeugt, sorry es ist so ausführliches:

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 

Antwort

6

Mein Rat ist so viel wie möglich in Pandas zu tun. Dies ist ein Standard-Ratschlag: "Mach es zuerst, dann sorge dich um die Leistung, wenn es wirklich zählt". Nehmen wir an, Sie haben das getan (hoffentlich haben Sie auch ein paar Tests geschrieben), und es ist zu langsam:

Profilieren Sie Ihren Code. (Siehe this SO answer, oder% prun in ipython verwenden).

Die Ausgabe von Prun sollte fahren, welches Bit zur nächsten zu verbessern.

  1. Pandas (Ihr Code pandorable, kann dies dazu beitragen viel).
  2. numpy (keine intermediären Series/DataFrames erstellen, bei dtypes vorsichtig sein)
  3. Cython (der letzte Ausweg).

Nun, wenn es sich um eine Linie mit Slicing zu tun ist (es ist wahrscheinlich nicht) setzen, dass winziger Teil in cython, Ich mag einzelne Python-Funktion entfernen, ruft Funktion Cython. An diesem Punkt sollte Zeug mit Cython verwenden numpy nicht Pandas, ich glaube nicht, Pandas wird nicht auf C (Cython kann nicht Schluss Arten).


Ihren gesamten Code in cython Putting tatsächlich nicht so viel helfen, dass Sie nur wollen, um die spezifischen Linien setzen oder Funktionsaufrufe, die sensible Leistung sind. Nur mit Cython zu arbeiten, ist eine gute Zeit.

Lesen Sie die enhancing performance section of the pandas docs *! Hier wird dieser Prozess (prun -> cythonize -> type) Schritt für Schritt mit einem realen Beispiel durchlaufen.

* Vollständig offen Ich habe es den Abschnitt der Dokumentation geschrieben! :)

+0

Putting meinen gesamten Code in Cython geholfen unglaublich!Von einer Übernachtung bis 20 Minuten !! Beim Überwachen der CPU-Zustände verbrachte die CPU in Python viel Zeit in C1 +. Aus diesem Grund ist die Frage eher eine Frage, wie man eine Beschleunigung der Arbeit erreicht, als eine Optimierung. Danke für die Dokumentation und andere Arbeit, die du machst. Es war die Grundlage, so weit zu kommen wie ich 8). Behandeln Pandas alle Zelltypen und leiten diese an Cython weiter? – SpmP

+0

Nun, es mag sein, aber ich denke, dass Sie eine effektivere Geschwindigkeit erreichen können, indem Sie nur einen kleinen Teil des Codes zythonisieren (das leistungsempfindliche Bit). Pandas behandelt verschiedene DTypen, wenn Sie Pandas-Methoden verwenden (diese sind bereits vecorisiert oder in Cython selbst geschrieben). –

+1

Das bedeutet, dass Sie in der Lage sein sollten, "mehr" von der Optimierung über das reine Cything zu beschleunigen. –

Verwandte Themen