我有一个这样的数据帧:
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'
),然后我们尝试将其解压缩为x
和y
。这恰好适用于'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])