2017-09-01 207 views
1

我有一个“链接”列的数据框,其中包含几千个在线文章的网址。每个观察都有一个URL。在将字典键分配给匹配行时将数据框与字典值进行过滤?

urls_list = ['http://www.ajc.com/news/world/atlan...', 
      'http://www.seattletimes.com/sports/...', 
      'https://www.cjr.org/q_and_a/washing...', 
      'https://www.washingtonpost.com/grap...', 
      'https://www.nytimes.com/2017/09/01/...', 
      'http://www.oregonlive.com/silicon-f...'] 

df = pd.DataFrame(urls_list,columns=['Links']) 

我另外有一个包含出版物名称密钥和域名为值的字典。

urls_dict = dict({'Atlanta Journal-Constitution':'ajc.com', 
        'The Washington Post':'washingtonpost.com', 
        'The New York Times':'nytimes.com'}) 

我想过滤的数据帧只得到这些意见在“链接”栏包含在字典中的值域,而同时在字典键分配出版物名称新专栏“出版物”。我设想的是使用下面的代码来创建“发布”列,然后从该列中删除None以在事实之后过滤数据帧。

pub_list = [] 

for row in df['Links']: 
    for k,v in urls_dict.items(): 
     if row.find(v) > -1: 
      publication = k 
     else: 
      publication = None 
     pub_list.append(publication) 

但是,列表pub_list,我得到的回报 - 虽然看起来做什么,我打算 - 是三倍长为我的数据帧。有人可以建议如何解决上述代码?或者,或者,建议一个更清洁的解决方案,它既可以(1)使用字典值(域名)过滤数据框的“链接”列,同时(2)创建字典键(发布名称)的新“发布” ? (请注意,df与只有一个简洁列在这里创建,实际文件将有许多列,因此我必须能够指定要过滤的哪一列。)

编辑:我想给出一些澄清的给出RagingRoosevelt的答案。我想避免使用合并,因为某些域可能不完全匹配。例如,与ajc.com我也想能够捕获myajc.com,并与washingtonpost.com我想要获得像live.washingtonpost.com这样的子域。因此,我希望在str.contains()find()in运算符中找到一种类型的“在字符串中查找子字符串”解决方案。

回答

0

我可以使用嵌套的字典解析(以及或者使用嵌套列表理解),还有一些额外的数据帧操作来清理列落空行来弄明白。

使用嵌套字典解析(或者更具体地,嵌套在字典解析列表解析的内侧):

df['Publication'] = [{k: k for k,v in urls_dict.items() if v in row} for row in df['Links']] 

# Format the 'Publication' column to get rid of duplicate 'key' values 
df['Publication'] = df['Publication'].astype(str).str.strip('{}').str.split(':',expand=True)[0] 

# Remove blank rows from 'Publication' column 
df = df[df['Publication'] != ''] 

类似地,使用一个嵌套列表理解

# First converting dict to a list of lists 
urls_list_of_lists = list(map(list,urls_dict.items())) 

# Nested list comprehension using 'in' operator 
df['Publication'] = [[item[0] for item in urls_list_of_lists if item[1] in row] for row in df['Links']] 

# Format the 'Publication' column to get rid of duplicate brackets 
df['Publication'] = df['Publication'].astype(str).str.strip('[]') 

# Remove blank rows from 'Publication' column 
df = df[df['Publication'] != ''] 
1

这里就是我想要做的:

  1. 使用DataFrame.apply一个新列添加到您的数据帧仅包含域。

  2. 使用DataFrame.merge(与how='inner'选项)合并你的域名字段上的两个数据帧。

这是一个有点脏使用循环做的东西dataframes如果他们只是迭代列或行,一般有,做同样的事情更清洁一个数据帧的方法。

如果你愿意,我可以用例子来扩展它。

编辑这是看起来像什么。请注意,我使用相当可怕的正则表达式来捕获域。

def domain_extract(row): 
    s = row['Links'] 
    p = r'(?:(?:\w+)?(?::\/\/)(?:www\.)?)?([A-z0-9.]+)\/.*' 
    m = re.match(p, s) 
    if m is not None: 
     return m.group(1) 
    else: 
     return None 

df['Domain'] = df.apply(domain_extract, axis=1) 

dfo = pd.DataFrame({'Name': ['Atlanta Journal-Constitution', 'The Washington Post', 'The New York Times'], 'Domain': ['ajc.com', 'washingtonpost.com', 'nytimes.com']}) 

df.merge(dfo, on='Domain', how='inner')[['Links', 'Domain', 'Name']] 
+0

谢谢。这工作,但我想避免使用'merge',因为一些域可能不是_exact_匹配。例如,使用'ajc.com',我也希望能够捕获'myajc.com',并使用'washingtonpost.com',我想要像'live.washingtonpost.com'这样的子域名好。因此,我希望找到一种类型的“在字符串中查找子字符串”解决方案w /'str.contains()'或'find()'来增加灵活性。 – dmitriys

+0

看起来应该可以做模糊匹配 https://stackoverflow.com/questions/13636848/is-it-possible-to-do-fuzzy-match-merge-with-python-pandas – RagingRoosevelt

相关问题