2013年9月11日 星期三

[R] 效能(3) hash套件

hash table其實就是一種key-value的資料格式
像是Java的HashMap、Python裡的Dictionary等等

在R裡的list也是一種key-value資料格式,個人覺得蠻好用的,想塞甚麼就塞甚麼
但是如果要塞進list的東西很多,就會遇到麻煩的效能問題,就是速度會拖慢啦

hash套件提供一種key-value的資料格式就叫hash
在執行速度上比list要來得快頗多


1. 使用.set(hash, key = value,...) 函數給定key-value值

> library(hash)
>
> test<- hash()
>
> .set( test,
+   name = "AirQuality",
+   May = datasets::airquality[which(datasets::airquality$Mon==5),],
+   Jun = datasets::airquality[which(datasets::airquality$Mon==5),],
+   Jul = datasets::airquality[which(datasets::airquality$Mon==5),],
+   Aug = datasets::airquality[which(datasets::airquality$Mon==5),]
+  )
> 

然後就可以像list一樣輸入key值叫出value了!

> head(test[["May"]])
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6
>
> head(test$May)
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6
>

或是直接insert key-value也可以

> test$"Sep"<- datasets::airquality[which(datasets::airquality$Mon==5),]
> 
> head(test[["Sep"]])
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6


2. 用 has.key(key,hash) 和 keys(hash) 函數檢查hash裡有哪些key

> has.key(c("May","Jun"),test)
 May  Jun
TRUE TRUE
> keys(test)
[1] "Aug"  "Jul"  "Jun"  "May"  "name" "Sep"

3. 用copy(hash)函數複製hash

官方文件裡建議不要直接用<- assign給某物件,所以在assign的時候最好用copy(hash)函數把hash直接複製給物件

> test2<- copy(test)


4. 用clear(hash)函數清理hash

如果直接用rm(hash)的話,hash所佔據記憶體容量並不會釋放,得先用clear(hash)把hash清空然後再刪掉

> clear(test)
> is.empty(test)
[1] TRUE
> rm(test)

5. 效能比較

最後來做一個無聊實驗,比較把資料塞進進list和塞進hash裡在效能上究竟熟優熟劣

> test1<- hash()
> test2<- list()
> system.time(
+  for (i in 1:10000){
+   test1[[as.character(i)]]<- 1:i
+  }
+ )
   user  system elapsed
  1.082   0.059   1.139
> system.time(
+  for (i in 1:10000){
+   test2[[as.character(i)]]<- 1:i
+  }
+ )
   user  system elapsed
  1.770   0.199   2.057

速度大概是兩倍左右,完畢!



2013年9月9日 星期一

[Python] 超級基本的網頁抓取

這篇是完全沒有基礎的我最近的小小心得

厲害的爬蟲技巧在這裡完全都沒有喔~~~

沒辦法誰叫我實在是嫩了!




抓取步驟(EX: 中央氣象局台北市氣溫預報)

第一步:

先到想去的網頁,記下網址(廢話)

http://www.cwb.gov.tw/V7/forecast/taiwan/Taipei_City.htmimport urllib2

到想抓的東西上反藍後「檢查元素」



找到他的標籤

像我要找的這個東西的標簽就是「td」!!




然後把python打開

把該import的套件import(他們都是python內建的,算是非常仁慈)

然後繼承SGMLParser寫成一個叫做WeatherList的類別

『is_td』是SGMLParser內建的,因為我們要抓的東西是被「td」標簽的,所使在這裡是使用is_td,如果有不同需求也有is_a之類的可以使用。之後定義start_td和end_td函數,最後定義handle_data函數把被td標簽包住的東西全寫進name裡面。

import urllib2
from sgmllib import SGMLParser
 
class WeatherList(SGMLParser):
    is_td=""
    name=[]
    def start_td(self, attrs):
        self.is_td = 1
    def end_td(self):
        self.is_td=""
    def handle_data(self, text):  
        if self.is_td:
                self.name.append(text)  

寫完之後就可以開始抓囉!
content = urllib2.urlopen('http://www.cwb.gov.tw/V7/forecast/taiwan/Taipei_City.htm').read()

Tempreature = WeatherList()
Tempreature.feed(content)

for i in Tempreature.name:
    if '\t' not in i:
        print i.decode('utf-8')

首先先用urllib2的工具把目標網頁上的東西抓下來

然後把name裡的東西排除不要的東西(「\t」這種東西就別來亂了)

再把東西印出來,就可以囉~~
26 ~ 30
舒適至悶熱
0 %
26 ~ 34
舒適至易中暑
0 %
26 ~ 30
舒適至悶熱
0 %
31.1
24.8
360.5
05:38
18:05
08:53
20:27
°C
°F