12

我的数据包含连续和分类特征的组合。下面是我的数据在 csv 格式中的样子的小片段(将其视为由在不同城市经营商店的超级连锁店收集的数据)

city,avg_income_in_city,population,square_feet_of_store_area,  store_type ,avg_revenue
NY  ,54504            , 3506908   ,3006                       ,INDOOR    , 8000091
CH  ,44504            , 2505901   ,4098                       ,INDOOR    , 4000091
HS  ,50134            , 3206911   ,1800                       ,KIOSK     , 7004567
NY  ,54504            , 3506908   ,1000                       ,KIOSK     , 2000091

你可以看到 avg_income_in_city、square_feet_of_store_area 和 avg_revenue 是连续值,其中 city、store_type 等是分类类别(为了保持数据的简洁性,我没有在这里展示更多的类别)。

我希望对数据进行建模以预测收入。问题是如何使用sklearn“离散化”连续值?sklearn 是否提供任何“现成的”类/方法来离散连续值?(就像我们在 Orange 例如 Orange.Preprocessor_discretize(data, method=orange.EntropyDiscretization())

谢谢 !

4

5 回答 5

10

答案是不。scikit-learn 中没有分箱。正如艾肯伯格所说,您可能想要使用 np.histogram。假设 scikit-learn 中的特征是连续的,而不是离散的。没有分箱的主要原因可能是大部分 sklearn 是在来自科学界的文本、图像特征或数据集上开发的。在这些设置中,分箱很少有帮助。您是否知道分箱确实有益的免费数据集?

于 2014-04-26T07:59:12.853 回答
10

更新(2018 年 9 月):截至 version 0.20.0,有一个函数sklearn.preprocessing.KBinsDiscretizer,它使用几种不同的策略提供连续特征的离散化:

  • 统一大小的垃圾箱
  • 内部具有“相等”数量的样本的箱(尽可能多)
  • 基于 K-means 聚类的 bins

不幸的是,目前,该功能不接受自定义间隔(这对我来说很遗憾,因为这正是我想要的,也是我最终来到这里的原因)。如果你想达到同样的效果,你可以使用 Pandas 函数cut

import numpy as np
import pandas as pd
n_samples = 10
a = np.random.randint(0, 10, n_samples)

# say you want to split at 1 and 3
boundaries = [1, 3]
# add min and max values of your data
boundaries = sorted({a.min(), a.max() + 1} | set(boundaries))

a_discretized_1 = pd.cut(a, bins=boundaries, right=False)
a_discretized_2 = pd.cut(a, bins=boundaries, labels=range(len(boundaries) - 1), right=False)
a_discretized_3 = pd.cut(a, bins=boundaries, labels=range(len(boundaries) - 1), right=False).astype(float)
print(a, '\n')
print(a_discretized_1, '\n', a_discretized_1.dtype, '\n')
print(a_discretized_2, '\n', a_discretized_2.dtype, '\n')
print(a_discretized_3, '\n', a_discretized_3.dtype, '\n')

产生:

[2 2 9 7 2 9 3 0 4 0]

[[1, 3), [1, 3), [3, 10), [3, 10), [1, 3), [3, 10), [3, 10), [0, 1), [3, 10), [0, 1)]
Categories (3, interval[int64]): [[0, 1) < [1, 3) < [3, 10)]
 category

[1, 1, 2, 2, 1, 2, 2, 0, 2, 0]
Categories (3, int64): [0 < 1 < 2]
 category

[1. 1. 2. 2. 1. 2. 2. 0. 2. 0.]
 float64

请注意,默认情况下,pd.cut返回 dtype 的 pd.Series 对象,Category其元素为 type interval[int64]。如果您指定自己的labels,输出的 dtype 仍将是 a Category,但元素将是 type int64。如果您希望系列具有数字 dtype,您可以使用.astype(np.int64).

我的示例使用整数数据,但它应该与浮点数一样工作。

于 2018-10-01T01:11:27.033 回答
5

您还可以考虑将分类变量呈现为数字,例如通过指标变量,该过程也称为单热编码

尝试

from sklearn.preprocessing import OneHotEncoder

并将其拟合到您的分类数据,然后使用数值估计方法,例如线性回归。只要类别不多(城市可能有点多),这可以很好地工作。

至于连续变量的离散化,您可以考虑使用调整后的 bin 大小进行 binning,或者等效地,在直方图归一化后进行统一 binning。numpy.histogram在这里可能会有所帮助。此外,虽然 Fayyad-Irani 聚类未在 中实现sklearn,但请随时检查sklearn.cluster数据的自适应离散化(即使它只是一维数据),例如通过 KMeans。

于 2014-04-24T11:56:15.310 回答
3

你可以使用 pandas.cut 方法,像这样:

bins = [0, 4, 10, 30, 45, 99999]
labels = ['Very_Low_Fare', 'Low_Fare', 'Med_Fare', 'High_Fare','Very_High_Fare']
train_orig.Fare[:10]
Out[0]: 
0     7.2500
1    71.2833
2     7.9250
3    53.1000
4     8.0500
5     8.4583
6    51.8625
7    21.0750
8    11.1333
9    30.0708
Name: Fare, dtype: float64

pd.cut(train_orig.Fare, bins=bins, labels=labels)[:10]
Out[50]: 
0          Low_Fare
1    Very_High_Fare
2          Low_Fare
3    Very_High_Fare
4          Low_Fare
5          Low_Fare
6    Very_High_Fare
7          Med_Fare
8          Med_Fare
9         High_Fare
Name: Fare, dtype: category
Categories (5, object): [High_Fare < Low_Fare < Med_Fare < Very_High_Fare < Very_Low_Fare]
于 2017-09-05T08:23:57.997 回答
1

感谢上面的想法;

要离散连续值,您可以使用:

  1. Pandas cutqcut函数(输入数组必须是一维的

或者

  1. sklearn 的KBinsDiscretizer函数(参数encode设置为“序数”)

    • parameter strategy=uniform将以与 pd.cut 相同的方式离散化
    • parameter strategy=quantile将以与 pd.qcut 函数相同的方式进行离散化

由于前面的答案中提供了 cut/qcut 的示例,因此让我们继续在 KBinsDiscretizer 上使用一个干净的示例:

import numpy as np
from sklearn.preprocessing import KBinsDiscretizer

A = np.array([[24,0.2],[35,0.3],[74,0.4], [96,0.5],[2,0.6],[39,0.8]])
print(A)
# [[24.   0.2]
#  [35.   0.3]
#  [74.   0.4]
#  [96.   0.5]
#  [ 2.   0.6]
#  [39.   0.8]]


enc = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
enc.fit(A)
print(enc.transform(A))
# [[0. 0.]
#  [1. 0.]
#  [2. 1.]
#  [2. 1.]
#  [0. 2.]
#  [1. 2.]]

如输出所示,每个特征都被离散化为 3 个 bin。希望这有帮助:)


最后注意事项:

  • 要比较cut versus qcut,请参阅此帖子
  • 对于您的分类特征,您可以利用KBinsDiscretizer(encode='onehot')对该特征执行 one-hot 编码
于 2020-08-19T08:49:07.587 回答