每月档案: 2013年7月

使用ACORA一次处理数百个停用词

“80%的数据分析是花费在清洁数据上,其中20%的花费是在抱怨清洁数据” – 长社 and 大数据宝

这是我听到的最好的报价之一 PyData 2013。当处理大量数据时,通常只有一小部分与一个数据相关’的分析,尝试清洁它可能会很痛苦。但这也是 基本阶段, 所以让’使它尽可能的无痛。

一个示例是巨大的日志文件。说我们’重新处理多TB的Apache日志文件,如下所示:

1
2
3
4
5
6
7
8
9
10
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-dropdown.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-scrollspy.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-tab.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-tooltip.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-popover.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-button.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-collapse.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-carousel.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-typeahead.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:39 -0500] “ GET /favicon.ico HTTP / 1.1” 404 4025 “-” “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”

这是包含数千行的有用数据,我们’d想使用 我之前提到的大文件处理脚本。但是,有些行’不关心–所以你可以写一个简单的条件:

1
2
3
4
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        如果 “ some_keyword” 线:
            做点什么()

What 如果 you have 2 东西 that you don’t want 在 each 线?

1
2
3
4
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        如果 (“ some_keyword” 线) (“ other_keyword” 线):
            做点什么()

What 如果 you have 3 东西 that you don’t want 在 each 线?

1
2
3
4
5
6
7
8
9
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        线_is_ok = 真正
        对于 停用词 [“ some_keyword”, “ other_keyword”, “不”]:
            如果 停用词 线:
                线_is_ok =
                打破 #退出循环
        如果 线_is_ok: #仅在line_is_ok未被篡改的情况下处理行
            做点什么()

但这变得超级低效,有点愚蠢。每个额外的关键字都需要通过该行。使用此代码,基本上所有情况都是最坏的情况。

带上ACORA!

阿科拉 是Stefan Behnel’的库基于 Aho-Corasick字符串匹配算法。无需深入了解其背后的数学原理,它基本上会将您拥有的所有停用词编译为一个über-停用词,这意味着在您的日志文件行中对该停用词进行一次扫描将检查所有停用词。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
阿科拉 进口 AcoraBuilder
 
#创建停用词列表-这些是条目
#我们想忽略的
停用词 = ['.js', '.ico', '.css', '.jpg', ...]
 
#将它们输入新的Acora Builder中
停用词_matcher = AcoraBuilder()
对于 停用词 停用词:
    停用词_matcher.(停用词)
 
#now让它构造超级停用词
停用词_matcher = 停用词_matcher.建立()
 
#this使用生成器迭代匹配项
#发现任何东西都会停止
对于 比赛 停用词_matcher.寻找者(线_from_log_file):
    打印 “找到匹配:{0}”.格式(比赛)

但是我们如何将其从以前集成到行扫描器中呢?像这样!

1
2
3
4
5
6
7
8
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        线_is_ok = 真正
        对于 比赛 停用词_matcher.寻找者(线):
            线_is_ok =
            打破 #退出循环
        如果 线_is_ok:
            做点什么()

We’ve用单个ACORA匹配器替换了整个多个停用词匹配的for循环。

性能说明

阿科拉很棒,但是如果只有几个停用词或只有几行,性能可能会下降。当您有大约20个以上的停用词并且至少有1000个左右的日志文件行要扫描时,它的性能最佳。

提取TLD(顶级域)–和怪异的怪癖会让你不高兴

I’ve been 我们ing 约翰·库科夫斯基‘优秀的Python域提取库“葡聚糖”最近。 TLDextract可以很容易地从URL中提取域名,例如:

1
2
3
>>> 葡聚糖 进口 提取
>>> 提取('http://stjamespublichouse.com/?p=106')
提取结果(子域='', ='ikigomu', 顶级域名='com')

为什么这有用?

这有很多应用–例如,如果您要创建链接到您网站的热门域名的摘要,则可能会有很多引荐网址:

1
ref_urls = ["http://www.google.com/somesearch", "http://sub.othersite.com/something", "//www.google.com/images", "http://xyz.yahoo.com/sample"] #etc等

您可以编写一些简单的代码来输出域:

1
2
3
4
5
6
7
8
9
葡聚糖 进口 提取
 
定义 抢域(网址):
    “返回URL的域”
    尝试:
        网址 = 提取(网址)
    例外:
        提高 例外(“此URL不起作用:{0}”.格式(网址))
    返回 '。'.加入((网址[1], 网址[2])) #连接域名和tld

并使用 词频计算器 从我以前的帖子中汇编出最热门的引用域名列表!看到我’ve修改了第10行,改为将域添加为键:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
算子 进口 项目获取器
馆藏 进口 定义aultdict
 
定义 域_frequencies(l):
    “获取网址列表'l'并返回列表清单
      其中每个项目是[域,频率],已排序
       descending."
    all_freqs = 定义aultdict(整型) #暂时保存值
    对于 项目 l:
        all_freqs[抢域(项目)] + = 1 #将域添加到defaultdict
    #将字典转换为列表列表
    all_freqs = [[k,v] 对于 k,v all_freqs.重复项()]
    #返回排序后的版本
    返回 已排序(all_freqs, =项目获取器(1), 逆转=真正)

哪个返回:

1
2
>>> 域_frequencies(ref_urls)
[[“ google.com”, 2], [“ yahoo.com”, 1], [“ othersite.com”, 1]]

为什么可以’你在第三个斜杠处用句号分隔’s before?

这是我一开始尝试做的事情:

1
2
3
4
5
定义 抢域(网址):
    返回 网址.分裂('/')[2].分裂('。')[-2:]
 
>>> 抢域("http://www.google.com/something")
>>> ['谷歌', 'com']

但是由于域名系统是顶级域名(例如.com),二级域名(例如.gov.uk),标准子域名(egiimgur.com)和拥有过多句号的人(例如www.dnr.state (.oh.us),这变得更加棘手,无法容纳所有内容。因此TLDextract实际上维护着Mozilla的本地副本’您系统上的ICANN域列表,可从以下网站下载: 

http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1

并从中基本上找到URL末尾的匹配项。非常好!

所以呢’标题中提到的问题?

不幸的是,使用Mozilla的警告’的清单是您得到一些看似奇怪的行为。有许多网站和公司从亚马逊请求其子域为TLD,并包含在列表中:

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Amazon CloudFront : //aws.amazon.com/cloudfront/
//由Donavan Miller请求<[email protected]> 2013-03-22
云前.
 
// Amazon Elastic Compute Cloud: //aws.amazon.com/ec2/
//由Osman Surkatty请求<[email protected]> 2013-04-02
计算.亚马逊.com
我们--1.amazonaws.com
计算-1.amazonaws.com
z-1.计算-1.amazonaws.com
z-2.计算-1.amazonaws.com
ap-东北-1.计算.amazonaws.com
ap-东南-1.计算.amazonaws.com
ap-东南-2.计算.amazonaws.com
欧盟 -西方-1.计算.amazonaws.com
SA--1.计算.amazonaws.com
我们-政府-西方-1.计算.amazonaws.com
我们-西方-1.计算.amazonaws.com
我们-西方-2.计算.amazonaws.com
 
// Amazon Elastic Beanstalk : //aws.amazon.com/elasticbeanstalk/
//由Adam Stein请求<[email protected]> 2013-04-02
弹豆.com

要DynDNS的东西:

的JavaScript
1
2
3
4
5
6
7
8
9
--认证的.com
-已保存.组织
-圆滑的.com
-优步.com
-非常-.组织
-非常-邪恶.组织
-非常-.组织
-非常-不错.组织
-非常-.组织

和更多… So you’如果您输入以下内容,将会绊倒:

1
2
>>> 提取("//scriptgang.elasticbeanstalk.com/getMagazine.html")
提取结果(子域='', ='脚本帮', 顶级域名='elasticbeanstalk.com')

而不是预期的“.com” 如 the 顶级域名.

简洁的方式来构建可迭代的Python频率表

这是编程中一个有趣且经常解决的任务,在NLP和数据科学中尤其普遍。通常有一个清单“things”有很多重复,并想知道哪些是最受欢迎的。

资料范例

1
我的清单 = [1,1,1,1,5,5,5,3,2,2,2,3,4,5,5,5,5,5,5,6,6,6,6]

要么:

1
my_sentence = “猫坐在垫子上看报纸”

哪个最受欢迎的号码?最受欢迎的字母是哪一个?

编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
馆藏 进口 定义aultdict
算子 进口 项目获取器
 
定义 freq_table(l):
    “获取列表'l'并返回列表列表
      每个项目都是['item',frequency],已排序
       descending."
    all_freqs = 定义aultdict(整型) #暂时保存值
    对于 项目 l:
        all_freqs[项目] + = 1 #添加到字典
    #将字典转换为列表列表
    all_freqs = [[k,v] 对于 k,v all_freqs.重复项()]
    #返回排序后的版本
    返回 已排序(all_freqs, =项目获取器(1), 逆转=真正)

对于我们的数据,我们现在得到:

1
2
>>> freq_table(我的清单)
[[5, 9], [1, 4], [6, 4], [2, 3], [3, 2], [4, 1]]

所以5是最受欢迎的项目,有9个出场。

1
2
>>> freq_table(my_sentence)
[['', 9], ['一种', 7], ['e', 5], ['t', 4], ['n', 3], ['d', 2], ['H', 2], ['p', 2], [, 2], ['r', 2], ['C', 1], ['m', 1], ['o', 1], ['T', 1], ['w', 1]]

因此,空间是最受欢迎的,其次是a,e和t。