假设我在熊猫中有一个数据帧,如下所示:
> my_dataframe
col1 col2
A foo
B bar
C something
A foo
A bar
B foo
其中行代表实例,列输入特征(不显示目标标签,但这是用于分类任务),即我试图从my_dataframe
中构建 X.
我如何有效地对此进行矢量化,例如 DictVectorizer
?
是否需要先将数据帧中的每个条目转换为字典?(这是上面链接中示例中的完成方式)。有没有更有效的方法可以做到这一点?
首先,我不知道您的样本数组中哪里是特征,以及观察值在哪里。
其次,DictVectorizer
不保存任何数据,仅涉及转换实用程序和元数据存储。转换后,它存储要素名称和映射。它返回一个 numpy 数组,用于进一步计算。numpy 数组(特征矩阵)的大小等于 features count
x number of observations
,其值等于观测值的特征值。因此,如果您知道自己的观测值和特征,则可以以您喜欢的任何其他方式创建此数组。
如果您希望 sklearn 为您完成此操作,则不必手动重建字典,因为它可以通过应用于转置数据帧的to_dict
来完成:
>>> df
col1 col2
0 A foo
1 B bar
2 C foo
3 A bar
4 A foo
5 B bar
>>> df.T.to_dict().values()
[{'col2': 'foo', 'col1': 'A'}, {'col2': 'bar', 'col1': 'B'}, {'col2': 'foo', 'col1': 'C'}, {'col2': 'bar', 'col1': 'A'}, {'col2': 'foo', 'col1': 'A'}, {'col2': 'bar', 'col1': 'B'}]
从scikit-learn 0.13.0(2014年1月3日)开始,to_dict()
方法有一个新的参数'records'
,所以现在你可以简单地使用这种方法,而无需额外的操作:
>>> df = pandas.DataFrame({'col1': ['A', 'B', 'C', 'A', 'A', 'B'], 'col2': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar']})
>>> df
col1 col2
0 A foo
1 B bar
2 C foo
3 A bar
4 A foo
5 B bar
>>> df.to_dict('records')
[{'col2': 'foo', 'col1': 'A'}, {'col2': 'bar', 'col1': 'B'}, {'col2': 'foo', 'col1': 'C'}, {'col2': 'bar', 'col1': 'A'}, {'col2': 'foo', 'col1': 'A'}, {'col2': 'bar', 'col1': 'B'}]
看看sklearn-pandas
它提供了您正在寻找的内容。相应的 Github 存储库在这里。
你绝对可以使用DictVectorizer
.由于DictVectorizer
需要类似dict
对象的可迭代对象,因此可以执行以下操作:
from sklearn.base import TransformerMixin
from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction import DictVectorizer
class RowIterator(TransformerMixin):
""" Prepare dataframe for DictVectorizer """
def fit(self, X, y=None):
return self
def transform(self, X):
return (row for _, row in X.iterrows())
vectorizer = make_pipeline(RowIterator(), DictVectorizer())
# now you can use vectorizer as you might expect, e.g.
vectorizer.fit_transform(df)
你想要从包含分类(或简单的字符串)的 pandas DataFrame 构建一个设计矩阵,最简单的方法是使用 patsy,这是一个复制和扩展 R 公式功能的库。
使用您的示例,转换将是:
import pandas as pd
import patsy
my_df = pd.DataFrame({'col1':['A', 'B', 'C', 'A', 'A', 'B'],
'col2':['foo', 'bar', 'something', 'foo', 'bar', 'foo']})
patsy.dmatrix('col1 + col2', data=my_df) # With added intercept
patsy.dmatrix('0 + col1 + col2', data=my_df) # Without added intercept
由此产生的设计矩阵只是带有一些额外信息的NumPy数组,可以直接用于scikit-learn。
添加了截距的示例结果:
DesignMatrix with shape (6, 5)
Intercept col1[T.B] col1[T.C] col2[T.foo] col2[T.something]
1 0 0 1 0
1 1 0 0 0
1 0 1 0 1
1 0 0 1 0
1 0 0 0 0
1 1 0 1 0
Terms:
'Intercept' (column 0)
'col1' (columns 1:3)
'col2' (columns 3:5)
请注意,patsy 试图通过将A
和bar
的影响合并到截距中来避免多重共线性。这样,例如,col1[T.B]
预测变量应解释为与分类为A
的观测值相关的B
附加效应。