使用 findall python 从推文中提取@mentions(给出不正确的结果)
Extracting @mentions from tweets using findall python (Giving incorrect results)
我有一个类似这样的 csv 文件
text
RT @CritCareMed: New Article: Male-Predominant Plasma Transfusion Strategy for Preventing Transfusion-Related Acute Lung Injury... htp://…
#CRISPR Inversion of CTCF Sites Alters Genome Topology & Enhancer/Promoter Function in @CellCellPress htp://.co/HrjDwbm7NN
RT @gvwilson: Where's the theory for software engineering? Behind a paywall, that's where. htp://.co/1t3TymiF3M #semat #fail
RT @sciencemagazine: What’s killing off the sea stars? htp://.co/J19FnigwM9 #ecology
RT @MHendr1cks: Eve Marder describes a horror that is familiar to worm connectome gazers. htp://.co/AEqc7NOWoR via @nucAmbiguous htp://…
我想从推文文本中提取所有提及(以“@”开头)。到目前为止我已经做到了
import pandas as pd
import re
mydata = pd.read_csv("C:/Users/file.csv")
X = mydata.ix[:,:]
X=X.iloc[:,:1] #I have multiple columns so I'm selecting the first column only that is 'text'
for i in range(X.shape[0]):
result = re.findall("(^|[^@\w])@(\w{1,25})", str(X.iloc[:i,:]))
print(result);
这里有两个问题:
首先:在 str(X.iloc[:1,:])
它给了我 ['CritCareMed']
这不正常,因为它应该给我 ['CellCellPress']
,在 str(X.iloc[:2,:])
它又给我 ['CritCareMed']
这是当然又不行了。我得到的最终结果是
[(' ', 'CritCareMed'), (' ', 'gvwilson'), (' ', 'sciencemagazine')]
它不包括第二行中的提及和最后一行中的两次提及。
我想要的应该是这个样子:
我怎样才能达到这些结果?这只是一个示例数据我的原始数据有很多推文所以这种方法可以吗?
你可以使用str.findall
方法来避免for循环,使用negative look behind来替换(^|[^@\w])
,这形成了另一个你不知道的捕获组在你的正则表达式中需要:
df['mention'] = df.text.str.findall(r'(?<![@\w])@(\w{1,25})').apply(','.join)
df
# text mention
#0 RT @CritCareMed: New Article: Male-Predominant... CritCareMed
#1 #CRISPR Inversion of CTCF Sites Alters Genome ... CellCellPress
#2 RT @gvwilson: Where's the theory for software ... gvwilson
#3 RT @sciencemagazine: What’s killing off the se... sciencemagazine
#4 RT @MHendr1cks: Eve Marder describes a horror ... MHendr1cks,nucAmbiguous
另外X.iloc[:i,:]
返回一个数据框,所以str(X.iloc[:i,:])
给你一个数据框的字符串表示,这与单元格中的元素有很大的不同,从中提取实际的字符串text
列,您可以使用 X.text.iloc[0]
,或者更好的遍历列的方法,使用 iteritems
:
import re
for index, s in df.text.iteritems():
result = re.findall("(?<![@\w])@(\w{1,25})", s)
print(','.join(result))
#CritCareMed
#CellCellPress
#gvwilson
#sciencemagazine
#MHendr1cks,nucAmbiguous
虽然您已经有了答案,但您甚至可以像这样尝试优化整个导入过程:
import re, pandas as pd
rx = re.compile(r'@([^:\s]+)')
with open("test.txt") as fp:
dft = ([line, ",".join(rx.findall(line))] for line in fp.readlines())
df = pd.DataFrame(dft, columns = ['text', 'mention'])
print(df)
产量:
text mention
0 RT @CritCareMed: New Article: Male-Predominant... CritCareMed
1 #CRISPR Inversion of CTCF Sites Alters Genome ... CellCellPress
2 RT @gvwilson: Where's the theory for software ... gvwilson
3 RT @sciencemagazine: What’s killing off the se... sciencemagazine
4 RT @MHendr1cks: Eve Marder describes a horror ... MHendr1cks,nucAmbiguous
这可能会快一点,因为您不需要在 df
构建完成后对其进行更改。
mydata['text'].str.findall(r'(?:(?<=\s)|(?<=^))@.*?(?=\s|$)')
与此相同:,但用于提及。
@.*?
对开始的单词进行 non-greedy 匹配
带有标签
(?=\s|$)
look-ahead为词尾或句尾
(?:(?<=\s)|(?<=^))
look-behind 以确保在单词中间使用 @ 时不会出现误报
正则表达式回顾断言 space 或句子开头必须在 @ 字符之前。
我有一个类似这样的 csv 文件
text
RT @CritCareMed: New Article: Male-Predominant Plasma Transfusion Strategy for Preventing Transfusion-Related Acute Lung Injury... htp://…
#CRISPR Inversion of CTCF Sites Alters Genome Topology & Enhancer/Promoter Function in @CellCellPress htp://.co/HrjDwbm7NN
RT @gvwilson: Where's the theory for software engineering? Behind a paywall, that's where. htp://.co/1t3TymiF3M #semat #fail
RT @sciencemagazine: What’s killing off the sea stars? htp://.co/J19FnigwM9 #ecology
RT @MHendr1cks: Eve Marder describes a horror that is familiar to worm connectome gazers. htp://.co/AEqc7NOWoR via @nucAmbiguous htp://…
我想从推文文本中提取所有提及(以“@”开头)。到目前为止我已经做到了
import pandas as pd
import re
mydata = pd.read_csv("C:/Users/file.csv")
X = mydata.ix[:,:]
X=X.iloc[:,:1] #I have multiple columns so I'm selecting the first column only that is 'text'
for i in range(X.shape[0]):
result = re.findall("(^|[^@\w])@(\w{1,25})", str(X.iloc[:i,:]))
print(result);
这里有两个问题:
首先:在 str(X.iloc[:1,:])
它给了我 ['CritCareMed']
这不正常,因为它应该给我 ['CellCellPress']
,在 str(X.iloc[:2,:])
它又给我 ['CritCareMed']
这是当然又不行了。我得到的最终结果是
[(' ', 'CritCareMed'), (' ', 'gvwilson'), (' ', 'sciencemagazine')]
它不包括第二行中的提及和最后一行中的两次提及。 我想要的应该是这个样子:
我怎样才能达到这些结果?这只是一个示例数据我的原始数据有很多推文所以这种方法可以吗?
你可以使用str.findall
方法来避免for循环,使用negative look behind来替换(^|[^@\w])
,这形成了另一个你不知道的捕获组在你的正则表达式中需要:
df['mention'] = df.text.str.findall(r'(?<![@\w])@(\w{1,25})').apply(','.join)
df
# text mention
#0 RT @CritCareMed: New Article: Male-Predominant... CritCareMed
#1 #CRISPR Inversion of CTCF Sites Alters Genome ... CellCellPress
#2 RT @gvwilson: Where's the theory for software ... gvwilson
#3 RT @sciencemagazine: What’s killing off the se... sciencemagazine
#4 RT @MHendr1cks: Eve Marder describes a horror ... MHendr1cks,nucAmbiguous
另外X.iloc[:i,:]
返回一个数据框,所以str(X.iloc[:i,:])
给你一个数据框的字符串表示,这与单元格中的元素有很大的不同,从中提取实际的字符串text
列,您可以使用 X.text.iloc[0]
,或者更好的遍历列的方法,使用 iteritems
:
import re
for index, s in df.text.iteritems():
result = re.findall("(?<![@\w])@(\w{1,25})", s)
print(','.join(result))
#CritCareMed
#CellCellPress
#gvwilson
#sciencemagazine
#MHendr1cks,nucAmbiguous
虽然您已经有了答案,但您甚至可以像这样尝试优化整个导入过程:
import re, pandas as pd
rx = re.compile(r'@([^:\s]+)')
with open("test.txt") as fp:
dft = ([line, ",".join(rx.findall(line))] for line in fp.readlines())
df = pd.DataFrame(dft, columns = ['text', 'mention'])
print(df)
产量:
text mention
0 RT @CritCareMed: New Article: Male-Predominant... CritCareMed
1 #CRISPR Inversion of CTCF Sites Alters Genome ... CellCellPress
2 RT @gvwilson: Where's the theory for software ... gvwilson
3 RT @sciencemagazine: What’s killing off the se... sciencemagazine
4 RT @MHendr1cks: Eve Marder describes a horror ... MHendr1cks,nucAmbiguous
这可能会快一点,因为您不需要在 df
构建完成后对其进行更改。
mydata['text'].str.findall(r'(?:(?<=\s)|(?<=^))@.*?(?=\s|$)')
与此相同:
@.*?
对开始的单词进行 non-greedy 匹配 带有标签(?=\s|$)
look-ahead为词尾或句尾(?:(?<=\s)|(?<=^))
look-behind 以确保在单词中间使用 @ 时不会出现误报
正则表达式回顾断言 space 或句子开头必须在 @ 字符之前。