使用 pandas 和 scikit-learn 对多维数组进行 one-hot 编码

Posted

技术标签:

【中文标题】使用 pandas 和 scikit-learn 对多维数组进行 one-hot 编码【英文标题】:one-hot encoding on multi-dimension arrays, using pandas or scikit-learn 【发布时间】:2018-02-23 01:42:01 【问题描述】:

我正在尝试为我的数据帧编码 one-hot。这是一个多维数组,我不知道该怎么做。数据框可能如下所示:

df = pd.DataFrame('menu': [['Italian', 'Greek'], ['Japanese'], ['Italian','Greek', 'Japanese']], 'price': ['$$', '$$', '$'], 'location': [['NY', 'CA','MI'], 'CA', ['NY', 'CA','MA']])

我想要的输出是这样的:

df2 = pd.DataFrame('menu': [[1,1,0], [0,0,1], [1,1,1]], 'price': [[1,0], [1,0], [0,1]], 'location': [[1,1,1,0], [0,1,0,0], [1,1,0,1]])

我不确定如何使用 pd.get_dummies 或 scikit-learn 来完成。 有人能帮我吗?

【问题讨论】:

处理数据框中的列表是使用 pandas 时最不想做的事情。这是一个糟糕的设计 - 考虑放弃它。 你可以看看MultiLabelBinarizer和我的answer here如何使用它。但缺点是您必须使用单独的 MultiLabelBinarizer 对象处理每一列。此外,您可能需要将列中的非列表项更改为 CA[CA] 之类的列表,因为这就是其中所需要的。 你能给出所有可能的位置值吗? @EspoirMurhabazi 就本例而言,我假设所有地点现在都是:NY、CA、MI、MA。 @cᴏʟᴅsᴘᴇᴇᴅ 感谢您的反馈。你能告诉我是否有更好的方法来看待这个问题?如果 pandas 是一个不好的开始方式,那么将我的数据集转换为其他格式没有问题。我只是不知道哪种方法最好。 【参考方案1】:

你可以使用:

#create list with one item values
df = df.applymap(lambda x: x if isinstance(x, list) else [x])
print (df)
       location                        menu price
0  [NY, CA, MI]            [Italian, Greek]  [$$]
1          [CA]                  [Japanese]  [$$]
2  [NY, CA, MA]  [Italian, Greek, Japanese]   [$]

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
#create Series for each column by list comprehension
vals = [pd.Series(mlb.fit_transform(df[x]).tolist()) for x in df.columns]
#concat to df
df2 = pd.concat(vals, keys=df.columns, axis=1)
print (df2)

       location       menu   price
0  [1, 0, 1, 1]  [1, 1, 0]  [0, 1]
1  [1, 0, 0, 0]  [0, 0, 1]  [0, 1]
2  [1, 1, 0, 1]  [1, 1, 1]  [1, 0]

【讨论】:

谢谢。我用了你的建议,它奏效了!我有错误“TypeError: unorderable types: str() > float()”,我认为这是由我的 nan 值引起的。我会想办法处理这种情况的。 是的,我测试它 - 将 CA 替换为 np.nan。那么如果是 NaN,你需要做什么?将 NaN 替换为诸如missing 之类的字符串?或者删除所有包含 NaN 的行? 将标量 NaN 替换为 missinguse df = df.fillna('missing').applymap(lambda x: x if isinstance(x, list) else [x]) 并删除所有带有 NaN 的行,使用 df = df.dropna().applymap(lambda x: x if isinstance(x, list) else [x]) 如果NaNs 在列表或标量中 - df = df.fillna('missing').applymap(lambda x: [i if pd.notnull(i) else 'missing' for i in x] if isinstance(x, list) else [x])

以上是关于使用 pandas 和 scikit-learn 对多维数组进行 one-hot 编码的主要内容,如果未能解决你的问题,请参考以下文章

将 pandas TimeStamp 与 scikit-learn 一起使用

使用 pandas 和 scikit-learn 对多维数组进行 one-hot 编码

在PyODPS DataFrame自定义函数中使用pandasscipy和scikit-learn

用scikit-learn和pandas学习Ridge回归

用scikit-learn和pandas学习线性回归

用scikit-learn和pandas学习线性回归