Python 如何在scikit学习中使用多个文本列对数据帧进行矢量化,而不丢失对原始列的跟踪

Python 如何在scikit学习中使用多个文本列对数据帧进行矢量化,而不丢失对原始列的跟踪,python,numpy,pandas,machine-learning,scikit-learn,Python,Numpy,Pandas,Machine Learning,Scikit Learn,我有几个pandas数据系列,希望训练这些数据映射到输出df[“output”] 到目前为止,我已将该系列合并为一个系列,并用逗号分隔 df = pd.read_csv("sourcedata.csv") sample = df["catA"] + "," + df["catB"] + "," + df["catC"] def my_tokenizer(s): return s.split(",") vect = CountVectorizer() vect = CountVecto

我有几个pandas数据系列,希望训练这些数据映射到输出df[“output”]

到目前为止,我已将该系列合并为一个系列,并用逗号分隔

df = pd.read_csv("sourcedata.csv")
sample = df["catA"] + "," + df["catB"] + "," + df["catC"]

def my_tokenizer(s):
    return s.split(",")

vect = CountVectorizer()
vect = CountVectorizer(analyzer='word',tokenizer=my_tokenizer, ngram_range=(1, 3), min_df=1) 
train = vect.fit_transform(sample.values)

lf = LogisticRegression()
lfit = lf.fit(train, df["output"])
pred = lambda x: lfit.predict_proba(vect.transform([x]))
问题是,这是一种冗长的方法,没有考虑
-每个类别中的唯一顺序。(“橙色香蕉”不同于“香蕉橙色”)
-文本是一个类别与另一个类别具有不同的意义(“一个类别中的美国”可能意味着原产国与目的地)

例如,整个字符串可以是:
pred(“美国,奇基塔香蕉,中国”)

A类:原产国
B类:公司和水果类型(订单不重要)
C类:目的地

我目前的做法忽略了任何类型的排序,并且出于某种原因在我的功能名称中生成了额外的空格(这会让事情变得更糟):


欢迎任何建议!!非常感谢

好的,首先让我们准备您的数据集,方法是选择相关列并使用
strip
删除前导和尾随空格:

sample = df[['catA','catB','catC']]
sample = df.apply(lambda col: col.str.strip())
在这里,您有两个选项可以选择如何为训练集将其矢量化。如果您的所有功能的级别数量很少(比如总共少于1000个),您可以简单地将它们视为分类变量,并设置
train=pd。获取虚拟对象(示例)
,将其转换为二进制指示符变量。在此之后,您的数据将如下所示:

catA_US   catA_CA ... cat_B_chiquita_banana   cat_B_morningstar_tomato ... catC_China ...
1         0           1                       0                            1   
...
请注意,变量名以其原始列开始,因此这确保模型知道它们来自何处。另外,您使用的是精确字符串,因此第二列中的词序将被保留

如果你有太多的级别来工作,或者你想考虑“代码> CATB</代码>中的单个单词以及双字节,你可以将你的<代码>计数向量> /代码>分别应用到每一列,然后使用并使用<代码> HStult连接所得的输出矩阵:

import scipy.sparse as sp
vect = CountVectorizer(ngram_range=(1, 3))
train = sp.hstack(sample.apply(lambda col: vect.fit_transform(col)))

尝试将dataframe映射到表示数据的字典列表(其中每个条目表示一列),然后编写一个自定义标记器函数,该函数接受字典作为输入并输出功能列表

在下面的示例中,我创建了一个自定义标记器,该标记器将遍历每个列,以便在将它们附加到标记列表之前,可以在函数内部对它们执行任何操作。然后使用Pandas将数据转换为字典列表

def my_tokenizer(d):
    # create empty list to store tokens
    tokens = []

    # do something with catA data
    tokens.append(d['catA'])

    # do something with catB data
    tokens.append(d['catB'].lower())

    return tokens

sample = df[['catA','catB','catC']]
vect = CountVectorizer(tokenizer=my_tokenizer)
train = vect.fit_transform(sample.to_dict(orient='records'))


你说的“橙色香蕉”是什么意思?奥兰治是这家公司吗?或者这些是分开的行?(在这种情况下,我不知道考虑它们独特的顺序意味着什么)好的单词袋不关心顺序,你可能正在寻找n-克或者也许是一个TF IDF方法,以便上下文可以被考虑,你也可以考虑天真的Bayes或者@ Max YMOO,这是一个例子来证明顺序。它没有其他意义。我举的“奇基塔香蕉”的例子更适合你understanding@EdChum我试过N-gram和你建议的所有其他变体的混合。不幸的是,我想要的是能够明确地告诉“预测器”它得到了什么特性。所以当我告诉它pred(“美国,奇基塔香蕉,中国”),它知道美国=来源,奇基塔香蕉=公司/类型,中国=目的地。至少,知道如何用逗号而不是空格分割要素会很有用。自定义标记器目前未按预期工作。你知道如何修改我的令牌模式来实现这一点吗?(目前u'(?u)\\b\\w\\w+\\b')抱歉,这不是我的专业知识,您所问的问题并不琐碎,可能值得在其他网站上发布一个关于数据科学方面的问题,例如目前您的问题似乎不是编程问题
def my_tokenizer(d):
    # create empty list to store tokens
    tokens = []

    # do something with catA data
    tokens.append(d['catA'])

    # do something with catB data
    tokens.append(d['catB'].lower())

    return tokens

sample = df[['catA','catB','catC']]
vect = CountVectorizer(tokenizer=my_tokenizer)
train = vect.fit_transform(sample.to_dict(orient='records'))