在将字典键分配给匹配行时将数据框与字典值进行过滤?
我有一个“链接”列的数据框,其中包含几千个在线文章的网址。每个观察都有一个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
运算符中找到一种类型的“在字符串中查找子字符串”解决方案。
我可以使用嵌套的字典解析(以及或者使用嵌套列表理解),还有一些额外的数据帧操作来清理列落空行来弄明白。
使用嵌套字典解析(或者更具体地,嵌套在字典解析列表解析的内侧):
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'] != '']
这里就是我想要做的:
使用DataFrame.apply一个新列添加到您的数据帧仅包含域。
使用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']]
谢谢。这工作,但我想避免使用'merge',因为一些域可能不是_exact_匹配。例如,使用'ajc.com',我也希望能够捕获'myajc.com',并使用'washingtonpost.com',我想要像'live.washingtonpost.com'这样的子域名好。因此,我希望找到一种类型的“在字符串中查找子字符串”解决方案w /'str.contains()'或'find()'来增加灵活性。 – dmitriys
看起来应该可以做模糊匹配 https://stackoverflow.com/questions/13636848/is-it-possible-to-do-fuzzy-match-merge-with-python-pandas – RagingRoosevelt