2013-05-09 4 views
13

Ich habe einen Pandas DataFrame mit einer date Spalte (zB: 2013-04-01) von dtype datetime.date. Wenn ich diese Spalte in X_train einfüge und versuche, das Regressionsmodell anzupassen, erhalte ich den Fehler float() argument must be a string or a number. Durch das Entfernen der date-Spalte wurde dieser Fehler vermieden.Regression mit Datumsvariable mit Scikit-learn

Was ist der richtige Weg, um die date im Regressionsmodell zu berücksichtigen?

-Code

data = sql.read_frame(...) 
X_train = data.drop('y', axis=1) 
y_train = data.y 

rf = RandomForestRegressor().fit(X_train, y_train) 

Fehler

TypeError         Traceback (most recent call last) 
<ipython-input-35-8bf6fc450402> in <module>() 
----> 2 rf = RandomForestRegressor().fit(X_train, y_train) 

C:\Python27\lib\site-packages\sklearn\ensemble\forest.pyc in fit(self, X, y, sample_weight) 
    292     X.ndim != 2 or 
    293     not X.flags.fortran): 
--> 294    X = array2d(X, dtype=DTYPE, order="F") 
    295 
    296   n_samples, self.n_features_ = X.shape 

C:\Python27\lib\site-packages\sklearn\utils\validation.pyc in array2d(X, dtype, order, copy) 
    78   raise TypeError('A sparse matrix was passed, but dense data ' 
    79       'is required. Use X.toarray() to convert to dense.') 
---> 80  X_2d = np.asarray(np.atleast_2d(X), dtype=dtype, order=order) 
    81  _assert_all_finite(X_2d) 
    82  if X is X_2d and copy: 

C:\Python27\lib\site-packages\numpy\core\numeric.pyc in asarray(a, dtype, order) 
    318 
    319  """ 
--> 320  return array(a, dtype, copy=False, order=order) 
    321 
    322 def asanyarray(a, dtype=None, order=None): 

TypeError: float() argument must be a string or a number 

Antwort

5

Sie haben zwei Möglichkeiten. Sie können das Datum in eine Ordinalzahl umwandeln, d. H. Eine Ganzzahl, die die Anzahl der Tage seit Jahr 1 Tag 1 darstellt. Dies können Sie mit einer datetime.datetoordinal Funktion tun.

Alternativ können Sie die Daten in kategoriale Variablen mit sklearns OneHotEncoder umwandeln. Er erstellt eine neue Variable für jedes einzelne Datum. Statt einer Spalte date mit den Werten ['2013-04-01', '2013-05-01'] haben Sie zwei Spalten: date_2013_04_01 mit den Werten [1, 0] und date_2013_05_01 mit den Werten [0, 1].

Ich würde den Ansatz toordinal empfehlen, wenn Sie viele verschiedene Daten haben, und den einen heißen Encoder, wenn die Anzahl der einzelnen Daten ist klein (sagen wir bis zu 10-100, abhängig von der Größe Ihrer Daten und welche Art der Beziehung, die das Datum mit der Ausgangsvariablen hat).

19

Der beste Weg besteht darin, das Datum in eine Reihe von kategorischen Merkmalen zu explodieren, die in boolescher Form unter Verwendung der 1-of-K-Codierung codiert sind (z. B. durch DictVectorizer). Hier sind einige der Features, die ab einem Zeitpunkt extrahiert werden können:

  • Stunde des Tages (24 boolean Funktionen)
  • Tage der Woche (7 boolean Funktionen)
  • Tage des Monats (bis zu 31 boolean Funktionen)
  • Monate des Jahres (12 boolean Funktionen)
  • Jahre (so viele boolesche Funktionen, wie sie verschiedene Jahre in Ihrem Datensatz) ...
sind

Dies sollte es ermöglichen, lineare Abhängigkeiten von periodischen Ereignissen bei typischen menschlichen Lebenszyklen zu identifizieren.

Zusätzlich können Sie das Datum auch mit einem einzelnen Float extrahieren: konvertieren Sie jedes Datum als die Anzahl der Tage seit dem letzten Datum Ihres Trainingssatzes und dividieren Sie durch die Differenz der Anzahl der Tage zwischen dem maximalen Datum und der Anzahl der Tage des Mindestdatums. Dieses numerische Merkmal sollte es ermöglichen, Langzeittrends zwischen der Ausgabe des Ereignisdatums zu identifizieren: z.B. eine lineare Steigung in einem Regressionsproblem, um die Entwicklung in den kommenden Jahren besser vorhersagen zu können, die nicht mit der booleschen kategorialen Variablen für das Jahr-Merkmal codiert werden kann.

+0

Ich kann keine direkte Lösung mit scikit finden-lernen, Datum (String-Format) in mehrere Features zu konvertieren, also habe ich es manuell date_object = datetime.strptime ('2016-25-05', '% Y /% d /% m ') ' wochentag 'drucken, datum_object.strftzeit ('% w ') – Spl2nky

+1

Ihre Antwort ist sehr gut. Aber ich denke, dass es in manchen Fällen wichtig ist, Ordnung zu halten, zum Beispiel: die Reihenfolge der Tage oder der Wochentage. Ich denke, es kommt auf das Problem an und verschiedene Wege auszuprobieren. – Barto

0

Bevor Sie die boolesche Codierung mit der von @ogrisel vorgeschlagenen 1-of-K-Codierung durchführen, können Sie versuchen, Ihre Daten anzureichern und mit der Anzahl der Features zu experimentieren, die Sie aus dem datetime-type, dh Tag der Woche, extrahieren können von Monat, Tag des Jahres, Woche des Jahres, Viertel, usw. Sehen Sie zum Beispiel https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DatetimeIndex.weekofyear.html und Links zu anderen Funktionen.