如何处理包含列表数据的列?

数据挖掘 机器学习 分类 数据 数据清理 特征工程
2021-10-12 23:07:48

我有一个数据集,我处理并创建了六个特征:

['session_id', 'startTime', 'endTime', 'timeSpent', 'ProductList',
   'totalProducts']

并且目标变量是一个二进制类(性别)。

功能“productList”是一个列表:

    df['ProductList'].head()
Out[169]:
0    [13, 25, 113, 13793, 2, 25, 113, 1946, 2, 25, ...
1    [12, 31, 138, 14221, 1, 31, 138, 1979, 1, 31, ...
2                               [13, 23, 127, 8754, 0]
3    [13, 26, 125, 5726, 2, 26, 125, 5727, 2, 26, 1...
4           [12, 23, 119, 14805, 1, 23, 119, 14806, 0]
Name: ProductList, dtype: object

现在,很明显我不能按原样使用此功能。我该如何处理这个功能?我可以展开列表并为每个列表项创建一行,但这是否符合我的目的?

更新:我在分解列表后应用了 OHE,它导致 10k+ 列,我的 GCP 实例和我的计算机无法处理;应用 PCA 时。

PS:有超过 17,000 种独特的产品。

4个回答

您基本上想为购买的每个产品创建一个列,因为列表中每个产品的存在或不存在本身就是一个特征。请参阅 Hadley Wickham 对整洁数据的定义。

话虽如此,您似乎拥有大量产品。为了避免维度的过程,我要做的是获取您的二进制购买/未购买特征(或者如果您拥有该数据,计数值可能会更有效)并进行降维以获得一组合理的特征。Latent Dirichlet Allocation(来自主题建模)、PCA、t-SNE、我们的 UMAP 都很容易实现,值得一试。PCA 是最不复杂且运行速度最快的,将是一个很好的基准。

当您拥有较小的特征列表时,您可能想尝试使用进一步选择最相关特征的分类器,例如梯度提升树。

您可以将productList其视为一个句子,并以与 NLP 中处理语言相同的方式对待它。

所以是的,如果你的独特产品集不是太大,那么展开列表并将每个产品写成一个独特的列是一种非常有效的方法。您还可以查看嵌入层,将这个想法扩展到“太大”的项目列表。

如果列表中项目的顺序很重要,您可能希望将列表分解为单独的行并查找对序列的预测。

编辑:作为对您的评论的回应,这里与推文的语义分析进行了类比:

我们可以将推文视为单词列表,例如"I am happy" -> ["I", "am", "happy"]. 这些列表的长度各不相同,但每个单词(大概)都来自英语(+一些我们将方便地忽略的俚语和新词)。我们可以拿一本英语词典,查找每个单词在该词典中的位置,并将该词替换为该词典中该词的索引。在我们运行的示例中,这可能看起来像[23, 54, 219]. 这与您的与单个产品相关的产品 ID 列表相同。

字典中只有有限数量的单词(类似地,您只有有限数量的产品),因此我们可以 OneHot 编码列表中的每个索引 ( [[0,0,..,1,...], [0,...,1,...,0,..], ...])。

现在有两个选择:(1)列表中向量的顺序无关紧要,在这种情况下,我们会将它们相加以获得每个示例的单个向量,您可以按照描述进行处理 - 或(2 ) 列表中向量的顺序确实很重要,在这种情况下,您可以将数组拆分为多个示例,一个用于列表中的每个向量,并添加另一个特征来表示它在所述列表中的位置。您现在有一个数据集,其中一列包含一个与其他所有列大小相同的向量,您可以将其重写为一组多列。

然后,您可以继续进行您认为对您的数据合理的任何分析,例如,使用简单方法进行聚类,或训练非线性嵌入。

一旦对产品进行 OHE,就会增加太多额外的维度。为了解决这个问题,您可以采用以下两种方法之一 -

  1. 使用Nicholas建议的标准技术减小尺寸

  2. 您还可以尝试使用有关产品的知识及其与目标变量(即性别)的关系来对产品列表进行聚类。
    这种情况的一个典型示例是将邮政编码转换为州代码。

创建您的 OHE 矩阵

    import numpy as np,pandas as pd
    ###This is your current productlist
    productlist = pd.DataFrame(np.random.randint(1,14807,(1000,14806)))

    ##This is a zero matrix with column count equal to product count, rows = data count
    productlist_ohe = np.zeros((1000,14806)) 

    ##I looped over productlist and make the OHE=1 based on row and product Id
    for index, row in productlist.iterrows():
        for elem in row:
            productlist_ohe[index][elem-1] = 1

目标究竟是什么?预测二元结果(在这种情况下为性别)?如果属实,您可以按照Nicholas建议的方式进行,但您也可以将问题视为高维问题,而不是(自己)进行降维,并使用 Lasso / Ridge / Elastic Net 来“自动”选择特征。在这种情况下,不需要任何特征工程。

这是该方法的R 实现Python也存在类似的包另见Ch。6.3 in Introduction to Statistical Learning有一个很好的概述。