【问题标题】:Extracting @mentions from tweets using findall python (Giving incorrect results)使用 findall python 从推文中提取@mentions(给出不正确的结果)
【发布时间】:2018-03-19 21:56:14
【问题描述】:

我有一个类似这样的 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')]

它不包括第二行中的提及和最后一行中的两个提及。 我想要的应该是这样的:

我怎样才能达到这些结果?这只是一个示例数据,我的原始数据有很多推文,所以这种方法可以吗?

【问题讨论】:

    标签: python regex pandas twitter mention


    【解决方案1】:

    您可以使用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
    

    【讨论】:

    • 如何从 df 中选择第一列?如果 iloc 给出数据框。我的文件中有多个列,我必须只处理第一列“文本”
    • 要选择第一列,您可以使用列名,即df.textdf['text'],也可以使用ilocdf.iloc[:,0]
    【解决方案2】:

    虽然您已经有了答案,但您甚至可以尝试像这样优化整个导入过程:

    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 已经构建后更改它。

    【讨论】:

    • 非常感谢,我也试试看 :)
    【解决方案3】:
    mydata['text'].str.findall(r'(?:(?<=\s)|(?<=^))@.*?(?=\s|$)')
    

    与此相同:Extract hashtags from columns of a pandas dataframe,但用于提及。

    • @.*? 对一个单词开始进行非贪婪匹配 带有标签
    • (?=\s|$) 预读词尾或句尾
    • (?:(?&lt;=\s)|(?&lt;=^)) 后视以确保在单词中间使用 @ 时不会出现误报

    正则表达式lookbehind断言空格或句子的开头必须在@字符之前。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-27
      • 2017-12-14
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多