29

我有一个带有 dtypedate列(例如:)的 Pandas 2013-04-01DataFrame datetime.date。当我包含该列X_train并尝试拟合回归模型时,我得到了错误float() argument must be a string or a number。移除该date列可避免此错误。

date在回归模型中考虑的正确方法是什么?

代码

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

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

错误

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
4

5 回答 5

37

最好的方法是使用 1-of-K 编码将日期分解为一组以布尔形式编码的分类特征(例如,由DictVectorizer完成)。以下是可以从日期中提取的一些特征:

  • 一天中的小时(24 个布尔特征)
  • 星期几(7 个布尔特征)
  • 一个月中的某一天(最多 31 个布尔特征)
  • 一年中的月份(12 个布尔特征)
  • 年(与数据集中不同年份的布尔特征一样多)...

这应该可以识别典型人类生命周期中周期性事件的线性依赖关系。

此外,您还可以将日期提取为单个浮点数:将每个日期转换为自训练集的最小日期以来的天数,然后除以最大日期和最小日期之间的天数之差. 该数字特征应该可以识别事件日期输出之间的长期趋势:例如,回归问题中的线性斜率,以更好地预测未来年份的演变,无法使用年份特征的布尔分类变量进行编码.

于 2013-05-13T15:13:44.050 回答
15

你有两个选择。您可以将日期转换为序数,即表示自第 1 天第 1 天以来的天数的整数。您可以通过 adatetime.datetoordinal函数执行此操作。

或者,您可以使用 sklearn 的OneHotEncoder将日期转换为分类变量。它所做的是为每个不同的日期创建一个新变量。因此,您将拥有两列,而不是像 column datewith values ,而是with values和with values 。['2013-04-01', '2013-05-01']date_2013_04_01[1, 0]date_2013_05_01[0, 1]

如果您有许多不同的日期,我建议使用该toordinal方法,如果不同日期的数量很少(假设最多 10 - 100 个,具体取决于数据的大小和日期的关系类型),我建议使用该方法与输出变量)。

于 2013-05-09T06:53:42.510 回答
3

在使用@ogrisel 建议的 1-of-K 编码进行布尔编码之前,您可以尝试丰富您的数据并使用可以从日期时间类型中提取的特征数量,即星期几、月份中的日期、日期一年、一年中的一周、季度等。参见例如https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DatetimeIndex.weekofyear.html和其他函数的链接。

于 2017-10-26T22:40:05.820 回答
0

通常最好将特征数量保持在较低水平,并且时间戳中不需要太多信息。在我的情况下,将日期保持为与初始时间戳的日差就足够了。这样可以保持顺序,并且只会留下一个(序数)特征。

df['DAY_DELTA'] = (df.TIMESTAMP - df.TIMESTAMP.min()).dt.days

当然,这不会在一天内识别行为(取决于小时)。因此,也许您想降低到最能识别数据中不断变化的行为的规模。

用了几个小时:

df['HOURS_DELTA'] = (df.TIMESTAMP - df.TIMESTAMP.min()).dt.components['hours']

上面的代码添加了一个带有 delta 值的新列,以删除旧的 TIMESTAMP,然后执行以下操作:

df = df.drop('TIMESTAMP', axis=1)
于 2019-06-27T14:39:31.690 回答
0

我通常将 DateTime 转换为感兴趣的特征,例如年、月、日、小时、分钟。

df['Year'] = df['Timestamp'].apply(lambda time: time.year)

df['Month'] = df['Timestamp'].apply(lambda time: time.month)

df['Day'] = df['Timestamp'].apply(lambda time: time.day)

df['Hour'] = df['Timestamp'].apply(lambda time: time.hour)

df['Minute'] = df['Timestamp'].apply(lambda time: time.minute)
于 2022-01-29T22:54:09.790 回答