我对数据科学还比较新手。我正在尝试使用LDA解决NLP聚类问题。在使用sklearn中的CountVectorizer
时遇到了问题。
我有一个数据框:
df = pd.DataFrame({'id':[1,2,3],'word':[['one', 'two', 'four'], ['five', 'six', 'nine'], ['eight', 'eleven', 'ten']]})df2 = df.copy().assign(word = df.word.map(lambda y: " ".join(y))) id word0 1 one two four1 2 five six nine2 3 eight eleven ten
我从网上找到了一段代码,对我的问题很有帮助:
cvectorizer = CountVectorizer(min_df=4, max_features=10000,ngram_range=(1,2))cvz = cvectorizer.fit_transform(df2['word'])
我想要做的就是为word列中的值添加某种权重因子。它的工作原理应该是这样的:word列中数组的第一个元素应该具有len(lengths of an array)
的权重,并且从数组的开始到结束按降序排列。
例如:对于id = 1的行,我希望出现以下情况:
{one:3, two:2, four:1}
其中整数值是我的权重参数。
之后,我希望这些加权值能够被输入到CountVectorizer
中。
我已经阅读了文档,但就是不知道如何解决我的问题。
回答:
这里的关键功能是split()
方法 – 通过它,你可以将你的单词列表变成字符串列表,同时也可以获得你想要分配给每个字符串的整数值。
最终答案: 这里是一个即插即用的字典制作方法和apply()
调用来应用它:
def make_dict(list1,list2): d = {} for k,v in zip(list1,list2): d[k] = v return ddf2['word'].apply(lambda x : (x.split(" "), [i for i in reversed(range(1,len(x.split(" "))+1))])).apply(lambda y : make_dict(y[0],y[1]))
这将返回一个Series,其中Series的每个元素是您为该特定行请求的字典。下面是对此表达式的解释。
解释: 首先使用列表推导式创建一个元组 – 元组的第一项是分割后的字符串列表,将成为字典的键。元组的第二项是分割后的整数列表,将成为字典的值(这些基本上只是通过range()
调用生成的反转列表,其参数来自开头提到的字符串分割方法)
In [1]: df2['word'].apply(lambda x : (x.split(" "), [i for i in reversed(range(1,len(x.split(" "))+1))]))Out[1]:0 ([one, two, four], [3, 2, 1])1 ([five, six, nine], [3, 2, 1])2 ([eight, eleven, ten], [3, 2, 1])
接下来,定义一个接受两个列表作为参数的函数(我们知道,从上面的操作来看,这两个列表必须是相同长度的列表,所以我们不需要强制检查它们是否长度相同,除非我们很谨慎)并将它们拼接成一个字典:
In [2]: def make_dict(list1,list2): ...: d = {} ...: for k,v in zip(list1,list2): ...: d[k] = v ...: return d
List1变成键的集合,list2变成值的集合。(请注意,如果键重复,例如你的列是“one one one”,这将覆盖旧的键。)
现在剩下的就是将第一个表达式的输出与上面定义的函数结合起来,我们可以通过另一个apply()
来实现:
In [3]: df2['word'].apply(lambda x : (x.split(" "), [i for i in reversed(range(1,len(x.split(" "))+1))])).apply(lambda y : make_dict(y[0],y[1]))Out[3]:0 {'one': 3, 'two': 2, 'four': 1}1 {'five': 3, 'six': 2, 'nine': 1}2 {'eight': 3, 'eleven': 2, 'ten': 1}Name: word, dtype: object