【问题标题】:Converting pandas series to iterable of iterables将熊猫系列转换为可迭代的可迭代对象
【发布时间】:2017-12-30 13:45:26
【问题描述】:

我正在尝试在 sklearn 中使用 MultiLabelBinarizer。我有一个 pandas 系列,我想将该系列作为输入提供给 MultiLabelBinarizer 的 fit 函数。但是,我看到 MultiLabelBinarizer 的拟合需要iterable of iterables 形式的输入。我不确定如何将 pandas 系列转换为所需的类型。

import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer

data = pd.read_csv("somecsvFile")
y = pd.DataFrame(data['class'])

mlb = MultiLabelBinarizer()
y = mlb.fit(???)

我尝试将其转换为 numpy 数组,尝试使用 pandas 的 iter 函数,但似乎没有任何效果。

请给我一些建议。

谢谢

Edit1:print(data['class'].head(10)) 的输出是:

0        func
1        func
2        func
3    non func
4        func
5        func
6    non func
7    non func
8    non func
9        func
Name: status_group, dtype: object

【问题讨论】:

  • 你的数据框是什么样的?这个解决方案很简单,我只需要知道你的 df 有哪些列。
  • 你能发布print(data['class'].head(10))的输出吗?
  • @cᴏʟᴅsᴘᴇᴇᴅ - 编辑问题以添加头部输出。

标签: python pandas scikit-learn


【解决方案1】:

你问了什么

MultiLabelBinarizer 接受一个可迭代的迭代。

df['class'] 是可迭代的,因为值是一维的。您可以将其设为二维并解决您的问题。

mlb.fit_transform(df[['class']].values)
# equivalently
# mlb.fit_transform(df['class'].values[:, None])

array([[1, 0],
       [1, 0],
       [1, 0],
       [0, 1],
       [1, 0],
       [1, 0],
       [0, 1],
       [0, 1],
       [0, 1],
       [1, 0]])

仔细观察
此示例有 3 个唯一值,将生成 3 列。

mlb.fit_transform([
    ['a'],
    ['b'],
    ['a'],
    ['c']
])

array([[1, 0, 0],
       [0, 1, 0],
       [1, 0, 0],
       [0, 0, 1]])

但是,我们也可以传递非统一的子列表

mlb.fit_transform([
    ['a'],
    ['b', 'a'],
    ['a'],
    ['c', 'b']
])

array([[1, 0, 0],
       [1, 1, 0],
       [1, 0, 0],
       [0, 1, 1]])

虽然您的案例没有利用这一点,但这就是为什么它需要一个可迭代的可迭代对象,以便它可以执行我刚刚展示的操作。


我会怎么做

因为MultiLabelBinarizer 可以做的比我们需要的多,我们也许可以用更锋利的工具做一些更好的事情

f, u = pd.factorize(df['class'].values)
np.eye(u.size, dtype=int)[f]

array([[1, 0],
       [1, 0],
       [1, 0],
       [0, 1],
       [1, 0],
       [1, 0],
       [0, 1],
       [0, 1],
       [0, 1],
       [1, 0]])

比较时间

%timeit mlb.fit_transform(df['class'].values[:, None])

10000 loops, best of 3: 191 µs per loop

%%timeit
f, u = pd.factorize(df['class'].values)
np.eye(u.size, dtype=int)[f]

10000 loops, best of 3: 68.8 µs per loop

【讨论】:

  • 感谢清晰的描述。我现在明白了。
【解决方案2】:

如何解决MultiLabelBinarizer's fit needs an input of form iterable of iterables:

In [8]: df
Out[8]:
      class
0      func
1      func
2      func
3  non func
4      func
5      func
6  non func
7  non func
8  non func
9      func

In [10]: import pandas as pd
    ...: from sklearn.preprocessing import MultiLabelBinarizer

In [11]: y = df['class'].str.split(expand=False)   # <--- NOTE !!!

In [12]: mlb = MultiLabelBinarizer()
    ...: y = mlb.fit_transform(y)
    ...:

In [13]: y
Out[13]:
array([[1, 0],
       [1, 0],
       [1, 0],
       [1, 1],
       [1, 0],
       [1, 0],
       [1, 1],
       [1, 1],
       [1, 1],
       [1, 0]])

更新: as proposed by @unutbu you can use pd.get_dummies()

In [21]: pd.get_dummies(df['class'])
Out[21]:
   func  non func
0     1         0
1     1         0
2     1         0
3     0         1
4     1         0
5     1         0
6     0         1
7     0         1
8     0         1
9     1         0

【讨论】:

  • @cᴏʟᴅsᴘᴇᴇᴅ,是的,该错误消息不是 100% 清楚的。谢谢! :)
  • 这似乎将 non func 解释为 2 个标签:nonfunc。如果 OP 希望 non func 成为与 func 不同的标签,那么 pd.get_dummies(df['class']).values 可能就足够了。
  • @unutbu,感谢您的评论!确实如此。我只是想向 OP 展示如何解决 fit needs an input of form iterable of iterables 错误。我也不确定MultiLabelBinarizer 是这种情况下的最佳选择...
  • 是的。这将“非函数”视为函数和非函数。我希望将其归类为单一标签。但我明白了。我现在就让它工作。顺便说一句,只是好奇为什么您认为 MultiLabelBinarizer 不是这里的最佳选择?
猜你喜欢
  • 2016-08-12
  • 2011-10-03
  • 2015-02-21
  • 1970-01-01
  • 2019-06-03
  • 2016-12-13
  • 2014-04-26
  • 1970-01-01
  • 2018-12-03
相关资源
最近更新 更多