【问题标题】:Filter only links in a dataframe based on certain domain name根据特定域名仅过滤数据框中的链接
【发布时间】:2019-09-30 02:44:49
【问题描述】:

我有一个有 5 列的 pandas 数据框。我需要根据列表中的域名过滤link 列上的数据框,并重复计算每个进程的行数。 假设我有以下数据框:

url_id | link
------------------------------------------------------------------------
1      | http://www.example.com/somepath
2      | http://www.somelink.net/example
3      | http://other.someotherurls.ac.uk/thisissomelink.net&part/sample 
4      | http://part.example.com/directory/files  

我想根据下面列表中的域名过滤数据框并统计每个结果的数量:

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']

以下是预期的输出:

domain       | no_of_links
--------------------------
example.com  |  2
other.com    |  0
somelink.net |  1
sample.com   |  0

这是我的代码:

from tld import get_tld 
import pandas as pd

def urlparsing(row):
    url = row['link']
    res = get_tld(url,as_object=True)
    return (res.fld)

link = ({"url_id":[1,2,3,4],"link":["http://www.example.com/somepath",
            "http://www.somelink.net/example",
            "http://other.someotherurls.ac.uk/thisissomelink.net&part/sample",
            "http://part.example.com/directory/files"]})

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
df_link = pd.DataFrame(link)

ref_dom = []
for dom in domains:   
    ddd = df_link[(df_link.apply(lambda row: urlparsing(row), axis=1)).str.contains(dom, regex=False)]     
    ref_dom.append([dom, len(ddd)])

pd.DataFrame(ref_dom, columns=['domain','no_of_links'])

基本上,我的代码正在运行。但是,当数据框的大小非常大(超过 500 万行),并且域名列表超过十万时,这个过程需要我一天的时间。 如果您有其他方法可以使其更快,请告诉我。任何帮助,将不胜感激。谢谢。

【问题讨论】:

    标签: python pandas dataframe filter


    【解决方案1】:

    您可以使用 df.str 函数的正则表达式和 findall 函数来完成

    domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
    pat = "|".join([f"http[s]?://(?:\w*\.)?({domain})" 
                     for domain in map(lambda x: x.replace(".","\."), domains)])
    match = df["link"].str.findall(pat).explode().explode()
    match = match[match.str.len()>0]
    match.groupby(match).count()
    

    结果

    link
    example.com     2
    somelink.net    1
    Name: link, dtype: int64
    

    对于 0.25 之前的 Pandas

    domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
    pat = "|".join([f"http[s]?://(?:\w*\.)?({domain})" 
                     for domain in map(lambda x: x.replace(".","\."), domains)])
    
    match = df["link"].str.findall(pat) \
    .apply(lambda x: "".join([domain for match in x for domain in match]).strip())
    
    match = match[match.str.len()>0]
    match.groupby(match).count()
    

    要获得具有 0 个链接的域,您也可以使用 df 加入所有域的结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      相关资源
      最近更新 更多