2007年3月19日 星期一

[EXCEL] 誰的出現次數最多?

 
  相關函數陣列公式 / COUNTIF() / MAX() / ROW()

   前一篇文章利用陣列公式在一堆請假清單中列出曾經請過假的人,這次我們來找找,誰是請最多假的「請假大王」?

##CONTINUE##
  要計算次數,當然要利用函數 COUNTIF(),如上圖 C 欄,C2 公式為

=COUNTIF($A$2:$A$11,A2)

  把公式直接往下複製,就可以算出每個人的請假次數。C2:C11 形成一個陣列,我們可以在這個陣列上做變化。

  例如,請假次數的最大值,D5 陣列公式

=MAX(COUNTIF($A$2:$A$11,A2:A11))

  那麼,這個請假次數最多的請假大王,到底是誰呢?D2 陣列公式

=INDIRECT("A"&MAX(
IF
(COUNTIF($A$2:$A$11,A2:A11)=MAX(COUNTIF($A$2:$A$11,A2:A11)),
ROW(A2:A11),
"")))


  我們來好好剖析這個公式。

  • 最內層的 COUNTIF($A$2:$A$11,A2:A11) 就是每個人的請假次數,也就是 C2:C11 這個陣列。
  • MAX(COUNTIF($A$2:$A$11,A2:A11)),就是請假次數的最大值。
  • IF(COUNTIF(...)=MAX(...), ROW(A2:A11),"") 則是說,如果某個人的請假次數等於最大值,就記下它所在的列數 ROW(),否則就記下空白。經過這個步驟,就可以只留下請假大王的所在位置。
  • 最後用外層的 MAX() 把這個列數取出來,再用 INDIRECT() 把位置轉成內容,完成!
  
  這個公式的架構,其實和之前高低標的公式很像,先把陣列公式利用

  IF(條件式,留下想要的值,空白)

  過濾成另一個陣列二,再從陣列二中取出想要的值,這裡是用 MAX(),高低標那裡是用 AVERAGE()。相同的架構,可以應用在各種地方,發揮你的想像力吧!

  實用上,C 欄可以整欄去掉,這裡只是用來說明陣列而已。

2007年3月6日 星期二

元宵逐風-新屋綠色走廊自行車道

 
  第一次騎自行車專用道,是多年之前,在台東關山鎮的環鎮自行車道。那時候還單身,單人單騎,追日逐風,青山秀水,迄今難忘。

  多年之後,小孩都五歲了,聽說桃園永安漁港旁有一條新屋綠色走廊自行車道,適合親子同遊,和鄰居相約,兩家人四大三小,又渡過愉快的一天。

##CONTINUE##
  以前租自行車只有一人單車和兩人協力車兩種,現在則是花樣眾多,從兩大一小的親子車,兩大兩小的家庭號,到六人座,八人座的全家福都有。簡單來說,只要你人來了,就會有適合的車型供你選擇,連還不會坐的小朋友都可以大人抱著坐後座,真是老少咸宜,大小通吃啊!

  這是我們租的兩大兩小家庭號,前座坐兩個大人,後座載丫丫加背包,一車搞定一家人。租金是一車二百元,兩車三百元,不限時間騎到爽。星期天早上遊客不多,是這個價格,中午過後遊客明顯變多,是不是維持這個價格就不知道了。

  自行車道全長約五公里,坡道平緩,一部份是林蔭小道,一部份是濱海小道。坐在車上不能直接看到大海,只能看到低矮的堤防,有點小可惜。

  我們自己帶了一輛兒童自行車去,讓兩個五歲小朋友輪流騎,累的人就坐大車休息。兩個小朋友都累了,就把小車放上大車車頂載著走。兩輛大車相互追逐,比一輛車單獨騎有趣多了,下次呼朋引伴多找些人一起來,應該會更有趣。

  不趕時間輕鬆踩,來回大約花了一個半小時,今天沒出大太陽,天氣陰涼,但是一個半小時下來,也是身體發熱微微出汗。車道中途有個可以看到海的涼亭,算是休息站,旁邊有廁所攤販,要的話也可以下去海邊玩沙。這次沒帶換洗衣物,就不下海了。

  這是路邊的行動咖啡車,小綠車很可愛,拍個照先。

  新屋綠色走廊最大的缺點,應該是汽機車管制不良了。雖然入口處有管制標制,但是不時可見汽機車穿梭其中,少數是車道旁的住家,這無可厚非,更多的是不守規矩的外來遊客。我就看到一輛 Escape 休旅車,空著車往前開,不久後又背著兩三輛單車往回開,空有休旅的裝備,卻沒有休旅的道德修養,鄙視它!

  交通:往桃園永安漁港方向 (114 縣道,中山路),漁港入口前不遠處,沿「新屋綠色走廊」或「永安雪森林」指標左轉進一條小路,經永安雪森林入口,續前行即為濱海小路,小路右方有一濱海大停車場,再往前行不久,左方有一小停車場,停車場旁小路可接新屋綠色走廊自行車道入口。

  租自行車:從漁港入口左轉之後,就陸續有自行車出租店;自行車道入口處更多租車店。建議等到了自行車道入口處再租車,因為濱海小路只有兩線道,而且沒有任何汽機車管制,車流量頗多,在此騎自行車很不安全。

2007年3月2日 星期五

[EXCEL] 排除重複的資料

 
  相關函數MATCH() / ROW() / SMALL() / INDEX()

  有一堆原始資料,其中可能有重複的部份,要如何才能排除重複的資料,每種資料只留下一筆?

  第一種方法,是先排序,把重複的部份集中在一起,再一筆一筆過濾排除。這個方法的好處是簡單,不需要任何函數或公式;壞處是,它會破壞掉原來的資料順序,而且必須從頭到尾用人工巡視一遍,可能會有疏漏

##CONTINUE##
  第二種方法,是用「格式化條件」把重複的部份變色,再一筆一筆過濾排除。詳細方法請參考這篇「[EXCEL]挑出重複的資料」。它的好處是不破壞原來的資料順序,而且可以一邊輸入新資料,一邊即時檢查新資料是否重複;壞處是,它一樣必須從頭到尾用人工巡視一遍,可能會有疏漏。如下圖 A 欄的紅色資料。

  第三種方法,也就是現在要介紹的方法,則是利用函數公式,直接挑出不重複的資料,這樣既不會破壞原來的資料順序,也不必從頭到尾用人工巡視一遍

  如上圖,有學生的請假記錄,如果想找出「二月份請過假的人」,也就是要把請過二天以上假的人只顯示一次,做法如下。

  假設名單範圍在 A1:A20,C 欄是用下列公式直接挑出不重複的請假名單:C2 輸入公式

=INDEX(A:A,SMALL(
IF(
IF(ISNA(MATCH($A$1:$A$20,A:A,0)),
"",
MATCH($A$1:$A$20,A:A,0))=ROW($A$1:$A$20),
ROW($A$1:$A$20),
""),
ROW()))

  這是一個陣列公式,請用 CTRL+SHIFT+ENTER 完成輸入。公式可往下複製。出現 #NUM! 時,表示名單已經列完了。

  這個公式的原理,是利用 MATCH(A2,A:A,0) 會在 A:A 找出第一個符合 A2 資料的位置列數,如 E 欄所示。如果 MATCH() 的結果和列數相同,如 E2,表示 A2 是第一次出現。如果 MATCH() 的結果和列數不相同,如 E5,表示 A5 不是第一次出現,也就是重複資料。

  利用 E 欄這個陣列,再加上 IF() 把陣列中的重複資料清為空白,就可以得到一個不重複名單列數的陣列了。再用 SMALL() 做排序,INDEX() 把列數轉為資料,就可以得到 C 欄的名單了。

  為了讓公式能使用在大小不同的變動名單上,我們允許名單範圍 A1:A20 中有空白。注意 E12 的 #N/A,就是因為 A12 為空白造成的。公式中的 ISNA() 就是為了把 #N/A 清為空白以免公式出錯才加的。

  實用上,可以把名單範圍設稍微大一點,當名單大小變動時,就不必每次更改公式了。

2008/10/21 補充:

  夏日大大提供了一個更簡便的公式,

  =T(INDEX(A:A,MIN(IF(COUNTIF(C$1:C1,$A$2:$A$20),4^8,ROW($A$2:$A$20)))))


  小弟大力推薦,有興趣的朋友可以研究一下。