代码之家  ›  专栏  ›  技术社区  ›  m33n

熊猫系列矢量化文本处理

  •  1
  • m33n  · 技术社区  · 6 年前

    我想使用矢量化操作改进我的Pandas代码。假设我有一个简单的数据框,其中有一个文本列,可能包含URL。

           Column1
    0  hello http://www.google.com
    1  bye www.mail.com www.docs.google.com/index
       ...
    

    此时,我正在迭代这些行并应用以下替换:

    s = re.sub('https*://[\w\.]+\.com[\w=*/\-]+|https*://[\w\.]+\.com|[\w\.]+\.com/[\w/\-]+',lambda x: re.findall('(?<=\://)[\w\.]+\.com|[\w\.]+\.com', x.group())[0], s)
    

    预期产出应为:

           Column1
    0  hello google.com
    1  bye mail.com docs.google.com
       ...
    

    有可能一次完成整个系列吗?

    4 回复  |  直到 6 年前
        1
  •  2
  •   Ben.T    6 年前

    根据你给出的例子,你可以使用 str.replace() :

    df['column1'] = df['column1'].str.replace('http|https|://|www.','') \ 
                                  #replace some patterm by nothing
                                  .str.replace('.com/[\w/\-]+','.com') 
                                  # replace specific pattern by other specific pattern
    

    然后,如果它不符合您的所有标准,您可以添加更多 .str.replace() 和你需要的那个

    编辑:在看了 documentation of Series.str.replace 相当于 re.sub() 所以你可以做:

    df['column1'] = df['column1'].str.replace('https*://[\w\.]+\.com[\w=*/\-]+|https*://[\w\.]+\.com|[\w\.]+\.com/[\w/\-]+',
                                              lambda x: re.findall('(?<=\://)[\w\.]+\.com|[\w\.]+\.com', x.group())[0])
    

    在内部,参数与您的 重新。sub() 关于你的问题。但你并没有真正得到你的预期输出,你用这个来保持“www.”。

        2
  •  1
  •   akasolace    6 年前

    保留替换所需的逻辑和代码,您可以按如下方式执行:

        import pandas as pd
        import re
    
        d = {'Column1': ["hello http://www.google.com", "bye www.mail.com www.docs.google.com/index"]}
        df = pd.DataFrame(data=d)
    
    
        f = lambda s : re.sub('https*://[\w\.]+\.com[\w=*/\-]+|https*://[\w\.]+\.com|[\w\.]+\.com/[\w/\-]+',lambda x: re.findall('(?<=\://)[\w\.]+\.com|[\w\.]+\.com', x.group())[0], s)
    
    
        print(df["Column1"].apply(f))
    
        3
  •  1
  •   PyRsquared    6 年前
    import re
    
    def replace_url(text):
        """
        Define the beginning of a url in a regex and replace any input text with an empty string using the regex
        INPUT: text (type = string)
        OUTPUT: text (type = string)
        """
        url_reg = re.compile(r"(http(s)?|www).*(\.)")
        return re.sub(url_reg, "", text)
    
    df['Column1'] = df['Column1'].apply(replace_url)
    

    在这里,我们明确定义了这个函数(替换URL的开头),然后以矢量化的方式将其应用于数据帧的整个列。这种方法通常比pandas replace方法更快,尽管我在这里没有计时,所以在这种情况下我不能确定。

        4
  •  0
  •   m33n    6 年前

    在多次尝试错误后,我找到了一个有效的解决方案。这远不是有效的,但现在我需要一些有用的东西,我会在不久的将来尝试优化它并更新帖子。

    def replace_url(text):
        pat = '(([https?://]*[www\.]*)([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?)'
        urls = re.findall(pat, text)
    
        for url in urls:
            text = text.replace(url[0], url[2])
    
        return text
    
    df['Column1'] = df['Column1'].apply(replace_url)
    

    多亏了@killerT2333,他给了我一些如何继续的直觉。