如何在pandas中使用apply实现嵌套循环



我有一个这样的数据帧:

text,                pos
No thank you.        [(No, DT), (thank, NN), (you, PRP)]
They didn't respond  [(They, PRP), (didn't, VBP), (respond, JJ)]

我想在pos上应用一个函数,并将结果保存在一个新列中。所以输出看起来像这样:

text,                pos                                           score
No thank you.        [(No, DT), (thank, NN), (you, PRP)]        [[0.0, 0.0, 1.0], [], [0.5, 0.0, 0.45]]
They didn't respond  [(They, PRP), (didn, VBP), (respond, JJ)]  [[0.0, 0.0, 1.0], [], [0.75, 0.0, 0.25]]
所以函数为列表中的每个元组返回一个列表(但函数的实现不是这里的重点,因为我只称之为get_sentiment)。我可以用嵌套循环来做,但我不喜欢这样。我想用一种更pythononic和Pandas Dataframe的方式来做:

这是我到目前为止所尝试的:

df['score'] = df['pos'].apply(lambda k: [get_sentiment(x,y) for j in k for (x,y) in j])

但是,它会抛出这个错误:

ValueError: too many values to unpack (expected 2)

so中有几个问题,但答案在r中。

更清晰:

get_sentiment函数是NLTK中的一个函数,它为每个单词分配一个分数列表(该列表为[positive score, negative score, objectivity score])。总的来说,我需要在Dataframe的pos列上应用该函数。

df['score'] = df['pos'].apply(lambda k: [get_sentiment(j[0],j[1]) for j in k ])

让我们将Pandas从等式中取出,并创建一个最小的可重复的问题示例—这与lambda本身有关:

def mock_sentiment(word, pos):
return len(word) * 0.1, 0, len(pos) * 0.1
data = [('No', 'DT'), ('thank', 'NN'), ('you', 'PRP')]
[mock_sentiment(x, y) for j in data for (x,y) in j] # reproduces the error

问题是每个j in data(例如('No', 'DT'))是一个单个元组,我们希望将其解包为x, y值。通过迭代in j,我们得到单独的字符串('No''DT'),然后我们尝试将其解压缩为xy。这恰好适用于'No''DT',但不适用于其他长度的字符串-即使这样,也不是期望的结果。

由于j已经是我们想要解包的元组,我们想要做的是在那里解包它,通过使用(x, y)而不是j进行迭代,并且没有任何嵌套的推导式:

[mock_sentiment(x, y) for (x, y) in data] # works as expected

因此,就是我们希望lambda在实际代码中返回给Pandas的内容(替换回您的名称和真实的情感函数):

df['score'] = df['pos'].apply(lambda k: [get_sentiment(x, y) for (x, y) in k])

相关内容

  • 没有找到相关文章

最新更新