使用 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 替换为 missing
use 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])
如果NaN
s 在列表或标量中 - 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 编码