2018年2月4日 星期日

關於抗體和抗體藥的一些小知識

近幾年來抗體藥變得頗為流行,不少藥廠研發抗體藥,其中包括治療阿茲罕默症的 aducanumab 和 solanezumab。藥名後面為 -mab 的代表是抗體藥,-mab 即為 mAb (monoclonal antibody)。


Figure: Wiki - Drug nomenclature

學名藥命名方式可參考這:Generic Name Stems

大家都知道抗體 IgG 長什麼樣子吧?就是兩個 heavy chains 和兩個 light chains,辨認抗原(antigen)的那端是 Fv (variable regions),另一端則是會被醣化(glycosylation)和引發免疫反應的 Fc (constant regions)。但是,你知道嗎?駱駝(camelid, llama)的體內有兩種抗體哦哦哦!一種是跟人類一樣的 IgG,另一種是只有 heavy chains 的抗體(HCAbs),這種特別的抗體的 Fv 叫做 HHV (下圖),又稱 nanobodies,雖然只有 heavy chain,但是對抗原的 binding affinity 並沒有比較弱,加上體積小,可以用來做抗體藥。


Figure: P. Holier & P. J. Hudson, Nature Biotechnology 2005 (doi: 10.1038/nbt1142)

簡單來說抗體藥有幾種,一種是整個 IgG,一種是只有 Fab,或甚至是只有 Fv。另外,近來更小的 single-chain Fv (scFv) 和 HHV (Nbs) 也引起關注,這兩種小抗體有個好處,就是比完整的 IgG 更容易穿透細胞,也容易被清洗掉(這點有好也有壞,要看用在哪),而且因為小又沒有 Fc,所以打入體內做為治療時不會引起不必要的免疫反應。

目前做抗體藥的方法有分三種,一種是大家比較知道的 in vivo,先打到動物裡,再取出 B cells 和 myeloma 合成 hybridomas 生產 monoclonal antibody。另一種是在 E. coli 裡面製造,這種大家應該也知道,在細菌裡面製造的優勢就是量大且便宜。最後一種是在酵母菌裡面製造,在酵母菌製造的優勢也是量大且便宜,但比細菌好的是它是 eukaryotic。

因為正常情況下,Fc 的部分會醣化,所以如果要做整個 IgG 的話,最好是在 mammalian cells 裡面製造,就是用 hybridomas,因為細菌並沒有 glycosylation,所以如果用細菌的話,還要再另外 in vitro glycosylation,這麼麻煩的話為什麼還要用細菌呢?如果你是要製造 Fab 或是 scFv 的話,因為不需要 glycosylation,這時候用細菌就可以省時省錢。

酵母菌的話,則是可以用來製造 IgG 或是 Fab, scFv。但是酵母菌的 glycosylation 和人類的不一樣,酵母菌的只有 mannose,生產出來的會附帶大量的 mannose,但是人類的是比較複雜的,通常不只有 mannose,還有 galactose 和 sialic acids 等等,所以需要改造酵母的基因,讓它能夠生產 galactose 和 sialic acid。所以同樣的,如果只是製造 Fab 或是 scFv 的話,用酵母菌會比用動物便宜。如果要製造整個 IgG 的話,雖然比較複雜一點,但是如果基因調控好了,除了可以大量生產外,還可以控制抗體的品質,省錢省時間。另外就是利用酵母菌的話,生產的蛋白質可以讓它釋放出來到培養液中,這樣純化起來會比較容易。


Figure: Jens Nielsen, Bioengineered 2013 (doi: 10.4161/bioe.22856)

當然用 E. coli 或酵母菌的話,不只能製造抗體藥,其他的蛋白質藥物也可以,例如目前市面上已有用酵母菌生產的胰島素(by Novo Nordisk)。

有興趣的可以看下面幾篇 papers。



References:

S. Steeland et al, Nanobodies as therapeutics: big opportunities for small antibodies. Drug Discovery Today (2016)

P. Holliger & P.J. Hudson, Engineered antibody fragments and the rise of single domains. Nature Biotechnology (2005)










2018年1月14日 星期日

怎樣才算 hard working

對不是我們這個領域的人來說,週末還要到實驗室叫做 hard working,但週末到實驗室其實沒什麼,尤其是如果只是禮拜六來收個實驗,或是禮拜天來用個 inoculation 好隔天可以做 miniprep。真要我週末來待整天,我還無法,會覺得好累,感覺沒放到假,對我就是草莓,我一直都覺得我算是很偷懶的 slacker,尤其跟我們實驗室的中國交換生相比更是(來很久變加拿大人的中國人週末幾乎不會來,除了我老闆),他們都是週末兩天來一天半的(沒來的半天是因為要買菜),像他們週末還跑 Western 這種事我是不會做的,除非真的有必要(不過到目前為止還沒有)。

但我之前被每天都待到七、八點,週末還都在實驗室待整天的中國人說我真是 hard working 時真是不解我 hard working 在哪?他是說他都快中午才來,他來的時候我做事都做到一半了,但是他待到八、九點,我都六點就走人了啊,而且我週末最多只待半天,除非我真的需要一個人靜一靜才會待比較久。

說到這,想到我研究所時系上同學週末也都是會來的,但也是只待個半天,就是收個實驗或做些簡單的實驗而已。然後從某天開始,隔壁實驗室的兩位同學說,他們覺得週末來實驗並不會做得比較順,做不出來的還是做不出來,並沒有因為週末來就做出來了,做得出來的週末沒來還是做得出來。他們經過比較之後,發現週末有來跟沒來結果並沒有差,實驗進度還是一樣,並沒有變得比較快或比較順,那週末幹嘛來呢?所以之後他們週末就不來了。

又想到我在大學時,在實驗室幫一位博士生做他的 side project,他本來都是早上八、九就點來的,但是從某天開始十點多才來,原因是他發現,他早來是因為想早走,但結果還是待到七、八點才走,那幹嘛早來呢?於是他就改成十點多才進實驗室。

之前 UBC 校長也說,研究生活不用只有工作,還是要有正常人的生活,週末多去交朋友,有些私人時間,多些社交空間,work-life balance 很重要,這也是他的親身經驗,他在研究不順的時候讓自己放鬆一下,過回正常人的生活後,研究就變順了。

好了,其實這篇只是想突然有感而發,覺得其實生活還是很重要的,還是需要 work life balance 才不會 burnout。



#加拿大人真沒競爭力XD










2018年1月13日 星期六

利用 ASO 治療阿茲罕默症

阿茲罕默症(Alzheimer's Disease, AD)的致病原因除了大家都知道的 β-amyloid (Aβ) 和 tau 堆積外,還有一個是 ApoE (apolipoprotein E)。ApoE 在腦中是由 astrocytes 製造的,原本的功能是運送膽固醇(cholesterol)到神經細胞,但並不知道它在 AD 裡扮演的角色為何。雖然早在 25 年前就發現它會增加 AD 的風險,帶有 ApoE4 基因得到 AD 的機率比帶有 ApoE3 的高三倍以上,但其詳細機制還不清楚。

目前認為 Aβ 是引起阿茲罕默症的原因,但它的堆積似乎和疾病的症狀沒有直接關係,在它之後發生的 tau 堆積反而會造成腦部的損害。那 ApoE 呢?它在其中扮演獨立的角色,還是牽線的角色?ApoE 的 variants 有三種:ApoE2-4,並不是每種都會增加阿茲罕默症的風險,目前所知只有 ApoE4 會。這期的 Neuron 有兩篇是關於 ApoE4,第一篇研究顯示 ApoE4 是造成 Aβ 開始堆積的原因。之前有研究顯示帶有 ApoE4 基因的人其 Aβ 堆積的 plaques 比沒帶得多,也許它是造成 Aβ 堆積的原因,或是它會促進 Aβ 的堆積。Aβ 在腦中一開始只是緩慢的微量堆積,稱為 seeding stage,到後期量邊多了以後,堆積速度會變快,而在這個過程中 ApoE 是從哪個階段開始參與呢?

Liu et al 的這篇研究用了可以控制 ApoE3 和 ApoE4 表現且帶有基因突變(APP/PS1)的 AD 老鼠,AD 老鼠在四、五個月大的時候會開始出現 Aβ 堆積的徵兆,然後六到九個月大是 Aβ 堆積最快速的時期,十個月大的時候則接近巔峰。他們讓老鼠的 ApoE 在三個不同時期開始表現:從剛出生到九個月大時都持續表現、只在前面六個月(也就是 Aβ 的 seeding stage)表現,或是在疾病的後期(也就是六到九個月大時)才表現。他們發現 ApoE4 從剛出生到九個月大都持續表現的老鼠,牠們的 Aβ 堆積有明顯的增加,而只表現 ApoE3 的老鼠則沒出現這個現象。他們也比較了只表現前六個月(出生到六個月大)和只表現後三個月(六到九個月大)的老鼠,發現前六個月有 ApoE4 表現的老鼠的 Aβ 堆積也有明顯增加,而只有後三個月有 ApoE4 表現的老鼠卻沒這個現象。另外,他們也發現 ApoE4 會讓 Aβ 無法被自然清理掉,使得它更容易堆積在腦內。

ApoE4 除了會加速 Aβ 的堆積外,也會增加 tau 對腦部的傷害。幾個月前刊在 Nature 的研究顯示 ApoE4 會加速 tau 的堆積,之前也有研究顯示 ApoE4 會增加 phospho-tau (p-tau) 的表現量。 Shi et al 的這個研究用了帶有突變 tau 基因(P301S)的老鼠,這個突變會產生大量 tau (是原本 endogenous tau 的五倍量),隨著年紀增長,insolube tau 會漸漸增加,最後形成 tau tangles,且這些堆積在腦部的 tau 都被高度磷酸化(phosphorylated)。這種老鼠在 1.5 個月大的時候腦部就會出現 tau 的堆積,在八個月大的時候即可觀察到腦細胞死亡和腦萎縮,海馬迴尤為嚴重。他們把這種老鼠本身的 ApoE4 基因拿掉,讓它不帶任何 ApoE 基因(ApoE KO, TEKO),或是拿掉 ApoE4 基因(TEKO)後再轉進其中一種人類的 ApoE 基因(P301S/ApoE2 (TE2), P301S/ApoE3 (TE3), P301S/ApoE4 (TE4))。

About AD transgenic mice: Tau P301S (Line PS19)

突變 tau 的老鼠在三個月大時,帶有人類 ApoE4 基因的老鼠腦部的 tau 表現量就比帶有其他種 ApoE 的高很多,其海馬迴裡的 p-tau 表現量也比較高。當老鼠九個月大的時候,他們檢視老鼠腦部,發現帶有 ApoE4 基因的老鼠腦部損害(萎縮)最嚴重,而帶有 ApoE2 的則是最輕。有趣的是沒帶有任何 ApoE 基因的老鼠(P301S/TEKO)腦部幾乎沒有被 tau tangles 損害;而不管是否帶有其中一種 ApoE,但是只帶有正常 tau 而非突變 tau 基因的老鼠,在九個月大的時候腦部也沒有萎縮的跡象。另外,帶有 ApoE4 基因的老鼠 (P301S/TE4)出現因為免疫反應引起的發炎,但是帶有其他 ApoE 的老鼠並沒有這個情形。而且同樣的,如果是正常 tau 而非突變 tau 的話,即便帶有 ApoE 也沒有出現免疫反應。體外試驗顯示並非只有 ApoE4 會使表現突變 tau 的細胞出現免疫反應和引起神經細胞的死亡,其他的 ApoE 也會,只是沒 ApoE4 那麼嚴重。

除了老鼠實驗,他們也檢視了 ApoE 和 tau 在人類患者中的關係是否和在老鼠中相同。大多數人帶有的是 ApoE3,少數沒有帶任何 ApoE 基因的人通常會出現膽固醇過高的情形,如果沒治療的話,可能會在年輕時便因心血管疾病而死。在這個研究裡, 他們檢視了 79 位因為 tau 堆積致死患者的大腦和他們帶有的 ApoE 基因,發現 Aβ 堆積的程度和腦部萎縮的程度沒有直接關係,反倒是帶有 ApoE4 的患者惡化的比較快,腦部萎縮、損害的比較嚴重。總結來說,這篇研究顯示相較於 Aβ,tau 和 ApoE4 比較像是使病情惡化的主因,ApoE 會加速 p-tau 的堆積,並且引發免疫反應造成發炎現象,最終導致腦細胞死亡。



既然 ApoE4 似乎是造成疾病的關鍵因素之一,於是這期 Neuron 的第二篇相關研究便是用了ASO (antisense oligo)去抑制 ApoE 的表現,看看是否會有效果。他們用了兩種老鼠,分別是帶有 AD 突變基因(APP/PS1)和人類 ApoE3 的老鼠(AD/ApoE3)和帶有人類 ApoE4 的 AD 老鼠(AD/ApoE4),然後在不同的時期把 ASO 打入這兩種老鼠:從剛出生第一天就給 ASO,或從六週大時(腦中已出現 plaques)才給 ASO,然後在十六週(四個月)大的時候檢視這兩種老鼠腦中的 Aβ 堆積情形。結果發現不管從何時開始打 ASO 都能有效降低 ApoE3 和 ApoE4 至約一半的量。至於在 Aβ 的部分,剛出生就給與 ASO 治療的老鼠,不管是 ApoE3 還是 ApoE4 的老鼠,牠們腦中的 Aβ 都明顯的降低了,並且 ApoE4 老鼠腦中的 plaques 也比沒 ASO 治療的低。如果是六週後才進行 ASO 治療的話,Aβ 量則沒有明顯的降低。不過有趣的是不管是剛出生就給 ASO,還是六週後才給 ASO,Aβ plaques 旁邊的 neuritic dystrophy 都有變少,即便六週才給 ASO 的老鼠腦中的 Aβ 量並沒有減少,表示 ApoE4 可能有參與 Aβ 引起的發炎反應。


由以上研究看來,ApoE4 雖然是配角,但卻是關鍵配角。好想知道我的 ApoE variants 是哪一種哦,希望不是 ApoE4。



延伸閱讀:阿茲罕默症新藥 Aducanumab



Articles:

WU in St. Louis Press Release / Newly ID’d role of major Alzheimer’s gene suggests possible therapeutic target

Alzheimer's News Today / Targeting ApoE in Brain Alone May Lead to Alzheimer’s Treatment, Researchers Say

NNR / Treatment Reduces Alzheimer's Damage


Papers:

Y Yoshiyama et al, Synapse Loss and Microglial Activation Precede Tangles in a P301S Tauopathy Mouse Model. Neuron (2007)

Y Shi et al, ApoE4 markedly exacerbates tau-mediated neurodegeneration in a mouse model of tauopathy. Nature (2017)

C Liu et al, ApoE4 Accelerates Early Seeding of Amyloid Pathology. Neuron (2017)

TV Huynh et al, Age-Dependent Effects of apoE Reduction Using Antisense Oligonucleotides in a Model of β-amyloidosis. Neuron (2017)










2018年1月10日 星期三

你的 strengths 是什麼?

今天去參加了一個 post-doc office 辦的 career workshop,在去之前他會要大家先上 Gallup Strength 做測試,看你的 strengths 在哪裡,因為有個理論是說,與其過份在意你的 weakness,不如好好了解你的 strengths,然後充份運用它、加強它,然後好好利用自己的 strengths,比較會在工作得到成就感和享受工作。另外有個比較有名的是 MBTI tests (費用也貴很多),也是測試人格測驗的一種,有的公司會付費讓員工做,我妹之前的公司就有讓他們做,加拿大政府好像也有讓政府員工做,主要是讓員工能更認識自己的特質,更能有效得工作。Gallup 檢測系統歸類了 34 種 strengths,學校付費讓我們免費做測試(原價好像是 CAD$25),可以得出你的 top 5 strengths (如果你想知道更多,例如你的全部 34 種的排列的話,則要加錢)。

Workshop 舉辦者有把所有參與者的 strengths 整理出來(如圖),看每個 stregnth 有多少人有,有趣的是你可以看到大多數人的 strengths 都集中在兩端:executing 和 strategic thinking。有趣的點在哪?去參加這個 workshop 的都是博士後,大家的 strengths 好像很理所當然都集中在這兩樣,似乎因為有了這些特質或 strengths 所以才有辦法在博班生涯中生存下來 XD,其中有一個人的 top 5 都是紅色的,聽主講人說這種人非常罕見(但我發現其實有好幾個人有四個 strengths 都是紅色的)。另一個有趣的點是最少的是 influencing 的部分,relationship building 可能因為研究或多或少需要合作,所以這部分還是有,但跟 executing 和 strategic thinking 比起來還是少很多。



這個統計反映出了一個 .... 算是教育系統還是人才培養系統需要加強的部分嗎?你會覺得這些人應該是要對社會有某些影響力的,但是他們(包括我)最欠缺的卻是這方面的能力,當然也許不是欠缺,畢竟這只是 top 5 的分析而已,可能是相較於其他 strengths,這些是比較弱的部分。如果讓商學院或社會學的來做這些,可能大家的 strengths 都集中在中間那兩項吧。XD



Executing: Leaders with dominant strength in the Executing domain know how to make things happen. When you need someone to implement a solution, these are people who will work tireless to get it done. Leaders with a strength to execute have the ability to "catch" an idea and make it reality.

Influencing: Those who lead by influencing help their team reach a much broader audience. People with strength in this domain are always selling the team's idea inside and outside the organization. When you need someone to take charge, speak up, and make sure your group is heard, look to someone the the strength to influence.

Relationship Building: Those who lead through Relationship Building are the essential glue that holds a team together. Without these strengths on a team, in many cases, the group is simply a composite of individuals. In contrast, leaders with exceptional Relationship Building strength have the unique ability to create groups and organizations that are much greater than the sum of their parts.

Strategic Thinking: Leaders with great strategic Thinking are the ones who keep us all focused on could be. They are constantly absorbing and analyzing information and helping the team make better decisions. People with strength in this strength continually stretch our thinking for the future.










2018年1月8日 星期一

腸道菌也許可以用來治療氣喘和過敏

下面列點筆記,沒有特別整理。

* 太乾淨的環境可能誤導免疫系統,使它在遇到些微的外來物(包括食物中的蛋白質)時變反應太過,造成過敏。

* 嬰兒在一歲就接受抗生素,得到氣喘的比例比較高。

* 他們給 germ-free mice (生長在無菌環境裡的無菌鼠)幼鼠和成鼠抗生素時,之後再給牠們常用的過敏原 ovalbumin (OVA) 去引發過敏反應,結果只有幼鼠出現明顯的哮喘反應,抗生素對成鼠沒有產生哮喘反應。另外,抗生素也影響了幼鼠和成鼠的腸道菌落,但是不同的改變。

* 他們收集了三百多個嬰兒出生時、三個月大時和一歲時的糞便,他們檢驗分析後,發現有四種腸道菌在有氣喘和沒氣喘的小孩中是不同的:Faecalibacterium, Lachnospira, Veillonella & Rothia。他們把這四種集合稱為 FLVR,音為 flavor。如果小孩在三個月大時有這四種細菌,得到氣喘的機率就很小。反之,如果你的 FLVR 很少,那就有較高的機率有氣喘。之後,他們把 FLVR 給無菌鼠吃,吃了細菌的無菌鼠出現肺炎和氣喘相關症狀比沒吃的還要輕。

* 去年 UCSF 的一篇研究顯示,當嬰兒在一個月大時如果缺少某些腸道菌,那他們在兩歲時出現過敏症狀和在四歲時出現氣喘症狀的機率比其他人高三倍。

* 2014 年時有篇研究顯示,五天的健康飲食就可以改變腸道菌的生態,吃很多青菜(plant-based diet)的人的腸道菌比吃很多肉(meat-based diet)的人健康。

* 家裡有養狗或貓的人,得到過敏或氣喘的機率比較小。家裡有養寵物的人,體內腸道菌落的種類比較多。

* 體內的腸道菌落是互相依附和互相影響的,因此產生出獨特的環境,改變一種細菌就會改變整個環境。

* 腸道菌並不是你吃進去後就會順利在你體內住下來了,很多情況是過幾天候它們就消失了,所以需要每天吃。



Articles:

Allergic Living / Why Are There So Many Food Allergies Today? (by Dr. S. Sicherer) Allergic Living (2015)

CIFAR / Missing bacteria linked with asthma (2015)

UCSC / Interview: B. Brett Finlay, microbiologist (2017)

Allergic Living / Inside the Microbiome: Why Good Gut Bacteria Is the Big Hope For Allergic Disease. (2017)


Papers:

SL Russell et al, Early life antibiotic‐driven changes in microbiota enhance susceptibility to allergic asthma. EMBO Reports (2012)

LA David et al, Diet rapidly and reproducibly alters the human gut microbiome. Nature (2014)

M Arrieta et al, Early infancy microbial and metabolic alterations affect risk of childhood asthma. Science Translational Medicine (2015)









2017年12月23日 星期六

R | Data manipulation (2): arrange, mutate, summarise

這篇介紹另外幾個處理資料的功能,上篇請看這裡:R | Data manipulation (1): select, filter, slice

詳細功能介紹請參考這兩頁:Working with Data - Part 1 & Intro to R - Part 3

練習的部分可以參考 slides: Working with Data - Part 1 (pdf)

這幾個功能在 dplyr 這個 package 裡面,所以要先跑。同時要用內建檔案 mtcars 來練習,所以也要叫出來。下面還會用檔案資料 flights,因為它在 nycflights13 這個 packages 裡面,所以也需要安裝。

library(dplyr)
library(nycflights13)
mtcars
flights

下面先介紹一個觀看檔案的功能。

Glimpse function: columns run down the page, and data runs across, making it possible to see every column in a data frame

glimpse() 和平常看檔案的方式不一樣。我們平常看檔案的時候,variables 是在第一列(rows),每個欄位(column)是一個 variables。但用 glimpse() 的話,它會橫向顯示每個 variable 的數據值。

下面先用資料檔案 flights 練習。

dim(flights)

dim: 顯示檔案資料的大小 dimension (row x column)

[1] 336776     19

上面顯示的結果告訴我們,共有 336776 個班機(observations),且用 19 個 variables 呈現各個班機的資訊。

glimpse(flights)

Observations: 336,776
Variables: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, ...
$ month          <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ day            <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ dep_time       <int> 517, 533, 542, 544, 554, 554, 555, ...

上面用 glimpse() 功能可以看到每班飛機的資訊(variables)包括有 year, month, day, dep_time 等等。

5. Arrange function: order observations (rows)

沒特別指令的話會由小到大排列。

Default setting: order mpg values from small to large. (依 mpg 的大小排列)

arrange(mtcars, mpg)

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
2  10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
3  13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
4  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
5  14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4

如果要由大到小排列的話,則用:desc()

Use desc() to sort in descending order.
Order mpg from large to small.

arrange(mtcars, desc(mpg))

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1  33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
2  32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
3  30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
4  30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
5  27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1

如果有兩個 variables 的話,會先排第一個,然後再在第一個裡面排第二個的大小順序。

mtcars %>%
   arrange(cyl, gear)

Arrange with cyl first; then within cyl, arrange gear.

上面的例子中,會先依照 cyl 的大小排列,再依 gear 的大小排列。

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
2  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
3  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
4  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
5  32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1

如果想讓兩個 variables 都由大到小排列,可以分開寫,也可以合在一起。

Reorder the mtcars in descending order of mpg and displacement (disp)

mtcars %>%
  arrange(desc(carb), desc(mpg))

或寫成這樣:

mtcars %>%
  arrange(desc(carb, mpg))

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1  15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
2  19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
3  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
4  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
5  19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
6  17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4

從上面可以看到是先依 carb 的大小排列,之後再依 mpg 的大小排列(最後四排當 carb 都是 4 的時候,mpg 是由大到小排列),但兩個都是由大到小。

Exercise

這邊我們用檔案資料 flights 來練習。

Q1. Which flights are the most delayed?

哪個班機起飛時間延遲最多,可以用 desc() 由大到小排列延遲的長度,第一個就是延遲最多的。下面先用 glimpse 呈現結果。

flights %>%
  arrange(desc(dep_delay)) %>%
  glimpse

Observations: 336,776
Variables: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, ...
$ month          <int> 1, 6, 1, 9, 7, 4, 3, 6, 7, 12, 5, 1, 2, ...
$ day            <int> 9, 15, 10, 20, 22, 10, 17, 27, 22, ...
$ dep_time       <int> 641, 1432, 1121, 1139, 845, 1100, 2321, ...
$ sched_dep_time <int> 900, 1935, 1635, 1845, 1600, 1900, 810, ...
$ dep_delay      <dbl> 1301, 1137, 1126, 1014, 1005, 960, ...

從上面顯示的最後一行 dep_delay 可以看到是由大到小排列。

如果不確定哪個 variable 是指延遲時間的話,可以用 help() 的功能來查看:?flights 或是 help(flights)

會在 R Studio 右下角的視窗中出現解釋框(如下圖,點圖可以放大),裡面寫:

dep_delay, arr_delay:
Departure and arrival delays, in minutes. Negative times represent early departures/arrivals.



下面是沒用 glimpse() 功能呈現,應該會比較清楚。

arrange(flights, desc(dep_delay))

# A tibble: 336,776 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>
 1  2013     1     9      641            900      1301     1242
 2  2013     6    15     1432           1935      1137     1607
 3  2013     1    10     1121           1635      1126     1239
 4  2013     9    20     1139           1845      1014     1457
 5  2013     7    22      845           1600      1005     1044
 6  2013     4    10     1100           1900       960     1342
 7  2013     3    17     2321            810       911      135
 8  2013     6    27      959           1900       899     1236
 9  2013     7    22     2257            759       898      121
10  2013    12     5      756           1700       896     1058
# ... with 336,766 more rows, and 11 more variables:
#   carrier &arr_delay <dbl>,lt;chr>, flight <int>, tailnum <chr>,
#   origin <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#   minute <dbl>, time_hour <dttm>

Q2: Which flights caught up the most time during the flight?

哪班飛機趕上的時間最多,就是說即便是延遲起飛,但是仍然準時抵達的,也就是延遲時間最短的(比預計的飛行時間短),這邊用延遲起飛的時間減掉延遲抵達的時間,再由大到小排列。

flights %>%
  arrange(desc(dep_delay - arr_delay)) %>%
  glimpse

Observations: 336,776
Variables: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, ...
$ month          <int> 6, 2, 2, 5, 2, 7, 7, 12, 5, 11, 5, 5, ...
$ day            <int> 13, 26, 23, 13, 27, 14, 17, 27, 2, 13, ...
$ dep_time       <int> 1907, 1000, 1226, 1917, 924, 1917, ...
$ sched_dep_time <int> 1512, 900, 900, 1900, 900, 1829, 1930, ...

不用 glimpse 顯示:

arrange(flights, desc(dep_delay - arr_delay))

# A tibble: 336,776 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>
 1  2013     6    13     1907           1512       235     2134
 2  2013     2    26     1000            900        60     1513
 3  2013     2    23     1226            900       206     1746
 4  2013     5    13     1917           1900        17     2149
 5  2013     2    27      924            900        24     1448
 6  2013     7    14     1917           1829        48     2109
 7  2013     7    17     2004           1930        34     2224
 8  2013    12    27     1719           1648        31     1956
 9  2013     5     2     1947           1949        -2     2209
10  2013    11    13     2024           2015         9     2251
# ... with 336,766 more rows, and 11 more variables:
#   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
#   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
#   hour <dbl>, minute <dbl>, time_hour <dttm>

可以指定 catchup 為 flights,再帶入 arrange,或是用 head 只顯示前十個 carrier。

flights %>%
  arrange(desc(dep_delay - arr_delay))
head(catchup$carrier, 10)

[1] "EV" "HA" "HA" "DL" "HA" "UA" "UA" "UA" "UA" "DL"

如果只看資料的前十個的話,則是下面這樣。

head(flights$carrier, 10)

[1] "UA" "UA" "AA" "B6" "DL" "UA" "B6" "EV" "B6" "AA"


6. Mutate function: 設定新的 variable,新設定的 variable 會顯示在最後一欄。

Make new variables: disp_l and wt_kg

1L = 61.0237 cu.in. (cubic inch)
1kg = 2.2 lbs

檔案資料裡面的 disp 單位是 cu.in.,我們把它轉換成 L,設定其為 disp_l。同時也把裡面原本單位為磅(lbs)的 wt 換算成 kg,指定其為 wt_kg。新訂的 disp_l 和 wt_kg 會顯示在最後兩的 column。

mtcars %>%
 mutate(disp_l = disp/61.0237,
        wt_kg = wt/2.2)

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb   disp_l     wt_kg
1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 2.621932 1.1909091
2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 2.621932 1.3068182
3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 1.769804 1.0545455
4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 4.227866 1.4613636
5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 5.899347 1.5636364

把重量換算成噸,指定其為:wt_tonnes
Include a variable for weight in tonnes (1t = 2,204.6 lbs)

mtcars %>%
  mutate(wt_tones = wt / 2.2046)

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb  wt_tones
1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 1.1884242
2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 1.3040914
3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 1.0523451
4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 1.4583144
5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 1.5603738


transmute: leave only the new variables

如果用 transmute() 的話,就只會顯示新訂的 disp_1 和 wt_kg。

mtcars %>%
  transmute(disp_l = disp/61.0237, wt_kg = wt/2.2)

     disp_l     wt_kg
1  2.621932 1.1909091
2  2.621932 1.3068182
3  1.769804 1.0545455
4  4.227866 1.4613636
5  5.899347 1.5636364
6  3.687092 1.5727273

Exercise

Q1. Compute speed in mph from time (in minutes) and distance (in miles)

同樣可以用 ?flights 查詢:

distance: Distance between airports, in miles
air_time: Amount of time spent in the air, in minutes

計算飛機的速度:mph = miles per hour

也就是飛行的距離 distance (in miles) 除以飛行的時間 air_time (in minutes)。

因為 air_time 是以分鐘為單位,所以我們必須先把它轉換成小時,也就是:air_time / 60

下面把速度指定為 speed

mutate(flights, speed = distance / (air_time / 60))

# A tibble: 336,776 x 20
    year month   day dep_time sched_dep_time dep_delay arr_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>
 1  2013     1     1      517            515         2      830
 2  2013     1     1      533            529         4      850
 3  2013     1     1      542            540         2      923
 4  2013     1     1      544            545        -1     1004
 5  2013     1     1      554            600        -6      812
 6  2013     1     1      554            558        -4      740
 7  2013     1     1      555            600        -5      913
 8  2013     1     1      557            600        -3      709
 9  2013     1     1      557            600        -3      838
10  2013     1     1      558            600        -2      753
# ... with 336,766 more rows, and 12 more variables:
#   arr_delay <dbl>, carrier <chr> flight <int>, tailnum <chr>,
#   origin <chr>, dest <chr>, air_time <dbl>,  distance <dbl>,
#   hour <dbl>, minute <dbl>, time_hour <dttm>, speed <dbl>

顯示整個檔案太長,看不到後面計算出來的 speed,所以用 select() 的功能挑出我們想看的幾個 variables。如果忘記 select() 是什麼、怎麼用的話,可以看前一篇

mutate(flights, speed = distance / (air_time / 60)) %>%
  select(carrier, distance, air_time, speed)

# A tibble: 336,776 x 4
   carrier distance air_time    speed
     <chr>    <dbl>    <dbl>    <dbl>
 1      UA     1400      227 370.0441
 2      UA     1416      227 374.2731
 3      AA     1089      160 408.3750
 4      B6     1576      183 516.7213
 5      DL      762      116 394.1379
 6      UA      719      150 287.6000
 7      B6     1065      158 404.4304
 8      EV      229       53 259.2453
 9      B6      944      140 404.5714
10      AA      733      138 318.6957
# ... with 336,766 more rows

Q2. Which flight flew the fastest?

哪個班機的速度最快?可以用 arrange() 功能由大到小排列出來,跟上面一樣只挑出我們想看的幾個 variables 來看。

flights %>%
  mutate(speed = distance / (air_time / 60)) %>%
  arrange(desc(speed)) %>%
  select(carrier, distance, air_time, speed)

# A tibble: 336,776 x 4
   carrier distance air_time    speed
     <chr>    <dbl>    <dbl>    <dbl>
 1      DL      762       65 703.3846
 2      EV     1008       93 650.3226
 3      EV      594       55 648.0000
 4      EV      748       70 641.1429
 5      DL     1035      105 591.4286
 6      DL     1598      170 564.0000
 7      B6     1598      172 557.4419
 8      AA     1623      175 556.4571
 9      DL     1598      173 554.2197
10      B6     1598      173 554.2197
# ... with 336,766 more rows

Q3. 把上面班機延遲練習的 Q2,用 select() 的功能挑出我們想看的幾項出來。

flights %>%
  mutate(delay_time = dep_delay - arr_delay) %>%
  arrange(desc(delay_time)) %>%
  select(carrier, dep_time, arr_time, air_time,
         dep_delay, arr_delay, delay_time)

# A tibble: 336,776 x 7
   carrier dep_time arr_time air_time dep_delay arr_delay delay_time
     <chr>    <int>    <int>    <dbl>     <dbl>     <dbl>      <dbl>
 1      EV     1907     2134      126       235       126        109
 2      HA     1000     1513      584        60       -27         87
 3      HA     1226     1746      599       206       126         80
 4      DL     1917     2149      313        17       -62         79
 5      HA      924     1448      589        24       -52         76
 6      UA     1917     2109      274        48       -26         74
 7      UA     2004     2224      295        34       -40         74
 8      UA     1719     1956      324        31       -42         73
 9      UA     1947     2209      300        -2       -75         73
10      DL     2024     2251      311         9       -63         72
# ... with 336,766 more rows

可以和上面排列前十的 carrier 的結果比對,看排列是不是一樣的。


7. Summarise / Summarize

功能和 mutate() 有點像,不一樣的是它會產生一個新的 data frame,並且是那欄(也就是那個 variable)所有觀察資料的總結。

Summarise works in an analogous way to mutate, except instead of adding columns to an existing data frame, it creates a new data frame. This is particularly useful in conjunction with ddply as it makes it easy to perform group-wise summaries.

例如算出 mpg 的平均值,可以用 mean() 的功能這樣算:

mean(mtcars$mpg)

[1] 20.09062

如果用 mutate() 的話會是這樣:

mutate(mtcars, mean(mpg))

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb mean(mpg)
1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4  20.09062
2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  20.09062
3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1  20.09062
4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1  20.09062
5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2  20.09062

同樣是算出 mean,但它會放在最後一欄,所以所有數值都一樣,因為它是全部觀察算出來的平均值。

如果用 summarise() 的話則是這樣,以一個 data frame 的樣式呈現出來:

summarise(mtcars, mean(mpg))

  mean(mpg)
1  20.09062

也可以幫平均值指定一個名稱 mpg_mean,直接寫在裡面即可。

summarise(mtcars, mpg_mean = mean(mpg)

  mpg_mean
1 20.09062

也可以設定三個,例如把 mpg 的平均值設為 mean_mpg,把重量的中間值設為 median_wt,然後把這兩者的比例設為 ratio

找出中間值用的功能是:median()

mtcars %>%
  summarise(mean_mpg = mean(mpg),
            median_wt = median(wt),
            ratio = mean_mpg/median_wt)

  mean_mpg median_wt    ratio
1 20.09062     3.325 6.042293

也可以全部寫在一行,下面同時把 mpg 的平均值直接設為 mpg,wt 的中間值設為 wt,把兩者的比例設為 ratio

summarise(mtcars, mpg = mean(mpg),
                  wt = median(wt),
                  ratio = mpg/wt)

       mpg    wt    ratio
1 20.09062 3.325 6.042293

除了算全部的平均值外,也可以分組算,例如算出 cyl 裡各種觀察值的平均值。下面先用 levels() 看 cyl 裡面有哪幾種,因為 cyl 的觀察值是數字,需要先把它換成 factor。

levels(factor(mtcars$cyl))

[1] "4" "6" "8"

由上面結果可以看出 cyl 的觀察值有三種:4, 6, 8。如果要看各個的 mpg 和重量平均值,可以用 group_by() 的功能。

mtcars %>%
  group_by(cyl) %>% 
  summarise(mean_mpg = mean(mpg), median_wt = median(wt))

# A tibble: 3 x 3
    cyl mean_mpg median_wt
  <dbl>    <dbl>     <dbl>
1     4 26.66364     2.200
2     6 19.74286     3.215
3     8 15.10000     3.755

也可以在一組裡面再分組算平均值,例如先用 am 分組後,在再裡面用 cyl 分組,先分的那個放前面,所以語法會是:group_by(am, cyl)

mtcars %>%
  group_by(am, cyl) %>%
  summarise(mpg = mean(mpg), wt = median(wt))

# A tibble: 6 x 4
# Groups:   am [?]
     am   cyl      mpg     wt
  <dbl> <dbl>    <dbl>  <dbl>
1     0     4 22.90000 3.1500
2     0     6 19.12500 3.4400
3     0     8 15.05000 3.8100
4     1     4 28.07500 2.0375
5     1     6 20.56667 2.7700
6     1     8 15.40000 3.3700

因為用 summarise() 算出來的結果本身就會轉換成一個 data frame,所以可以把這個 data frame 指定一個名稱,例如為 cars_am_cyl,這樣之後想要看的時候便不需要打全部的語法,只要叫出 cars_am_cyl 即可看。

cars_am_cyl <- mtcars %>%
  group_by(am, cyl) %>%
  summarise(mpg = mean(mpg), wt = median(wt))

cars_am_cyl

因為 cars_am_cyl 已經是一個 data frame,也可以直接用它來做運算,因為上面設定時已經先用 am 分好組了,所以算平均值的時候會依這個分。

cars_am_cyl %>%
  summarise(mpg = mean(mpg), wt = median(wt))

# A tibble: 2 x
     am      mpg    wt
  <dbl>    <dbl> <dbl>
1     0 19.02500  3.44
2     1 21.34722  2.77

也可以相反設試試看,先用 cyl 分組後再依 am 分組運算,也就是 group_by(cyl, am),然後和上面比較有何不同。

cars_cyl_am <- mtcars %>%
  group_by(cyl, am) %>%
  summarise(mpg = mean(mpg), wt = median(wt))

cars_cyl_am

# A tibble: 6 x 4
# Groups:   cyl [?]
    cyl    am      mpg     wt
  <dbl> <dbl>    <dbl>  <dbl>
1     4     0 22.90000 3.1500
2     4     1 28.07500 2.0375
3     6     0 19.12500 3.4400
4     6     1 20.56667 2.7700
5     8     0 15.05000 3.8100
6     8     1 15.40000 3.3700

因為上面是先用 cyl 分組,所以接下來用 cars_cyl_am 來做運算的話,會算出 cyl 裡各組的平均值。

cars_cyl_am %>%
  summarise(mpg = mean(mpg), wt = median(wt))

# A tibble: 3 x 3
    cyl      mpg      wt
  <dbl>    <dbl>   <dbl>
1     4 25.48750 2.59375
2     6 19.84583 3.10500
3     8 15.22500 3.59000

Exercise

Q1. Compute the minimum and maximum displacement for each engine type (vs) by transmission type (am)

在各個引擎的種類中依 am 分組後,找出其中的最大值和最小值,因此要先依引擎分類,再在其中依 am 分組,也就是:group_by(vs, am)

最大值和最小值的功能為:max()min()

mtcars %>%
  group_by(vs, am) %>%
  summarise(min = min(disp), max = max(disp))

# A tibble: 4 x 4
# Groups:   vs [?]
     vs    am   min   max
  <dbl> <dbl> <dbl> <dbl>
1     0     0 275.8   472
2     0     1 120.3   351
3     1     0 120.1   258
4     1     1  71.1   121

Q2. Which destinations have the highest average delays?

flights %>%
  group_by(dest) %>%
  summarise(avg_delay = mean(arr_delay, na.rm = TRUE)) %>%
  arrange(desc(avg_delay))

# A tibble: 105 x 2
    dest avg_delay
   <chr>     <dbl>
 1   CAE  41.76415
 2   TUL  33.65986
 3   OKC  30.61905
 4   JAC  28.09524
 5   TYS  24.06920
 6   MSN  20.19604
 7   RIC  20.11125
 8   CAK  19.69834
 9   DSM  19.00574
10   GRR  18.18956
# ... with 95 more rows


8. Boxplot

接下來試著畫箱圖,如果想畫出在 cyl < 8 的資料中,mpg 對 cyl 的反應,也就是:

x-axis: cyl < 8
y-axis: mpg, response to cyl

boxplot 的語法是:boxplot(formula, data = )

formula 是指兩軸(也就是兩個 variables)的關係,在這裡是: y ~ x 

表示 Y-axis 對 X-axis 的反應,所以也就是:boxplot(y ~ x, data = )

最後用 subset =  的功能挑出你要的,在這個例子裡就是 cyl < 8

boxplot(mpg ~ cyl, data = mtcars, subset= cyl < 8)



也可以用 %>% 分開寫。

You can use . as a placeholder when the “data” argument is in the second position.

mtcars %>%
  filter(cyl < 8) %>%
  boxplot(mpg ~ cyl, data = . )

在上面的語法裡,當前面已經表示過用的資料是 mtcars 的時候,後面在 boxplot() 裡面 data 的部分就可以用 "." 替代,也就是:data = . 

也可以用 ggplot2 來畫圖,用 ggplot 裡的 geom_boxplot() 畫的話,語法就是這樣:

ggplot(mtcars %>%
         filter(cyl < 8), aes(factor(cyl), mpg)) +
  geom_boxplot()

因為 cyl 是數字,所以要需要先把它變成 factor,想更了解的話可以參考這篇:R | ggplot: Point plot & Box plot

也可以先把畫圖要用的資料用 subset() 的功能挑出來,也就是 cyl < 8 的部分。我們可以把挑出來的部分指定成一個新的 data frame,下面我們把指定其為 cyl_sub,然後再用它來畫圖。

cyl_sub <- subset(mtcars, cyl < 8)

ggplot(cyl_sub, aes(factor(cyl), mpg)) + geom_boxplot()



好了,這篇就先到這吧。









2017年12月21日 星期四

CBC / Myth or Science: 關於大便的一些事

今天去了一個 Nerd Nite 的活動,因為這次是今年的最後一次,所以除了有科學的講題外,還有個小遊戲,小遊戲很有趣但不是重點,先講主題。

這次的講者是 BC CDC 的一位科學家:Dr. Jennifer Gardy

連結是她參與的 CBC 科學性節目,叫 Myth or Science,然後她今天講的是關於便便的:The Nature of Shit,主要是放不久前錄好的影片,但是聲音還沒後製上去,所以是邊看無聲的影片她邊講,預計在明年二月 on air 的樣子。

她這次關於便便的影片分三個部分,第一個很有趣,就是她吃了一個膠囊攝影機,攝影機全程錄下它從食道進入胃,再到大腸、小腸的過程。藉由膠囊攝影機,你可以清楚看到胃裡面長什麼樣子,它的皺摺等等。對了對了,你可以看到賁門和幽門,我看到的時候還以為是肛門 😅。然後還可以看到大腸裡面的皺摺和微生物等等,超酷的。不過當我清楚看到講者的胃裡面和大腸裡面長什麼樣子的時候,有種「哎呀,秘密都讓人看光惹,好害羞呀!」的感覺,不知道各位如果在公開場合讓大家看你胃裡面的皺摺和大腸裡面的微生物時,會不會有這種尷尬害羞的感覺。

第二個部分是玉米真的是「明天還會再見到」的食物嗎?😆 她為了做這個一連兩天每餐都吃玉米,之後再從自己的便便裡挑出玉米寄給她在多倫多 U of Guelph 的好友分析(她說:反正他一定是叫他的學生分析 XD),結果分析出來後發現便便裡拿出來的玉米上面帶有好多微生物,他們還用 EM 看玉米,好高級。之後她們跑到(美國的) Cambridge 抽取 sewage,看看裡面有哪些微生物和 chemicals。檢驗微生物可以得到一些關於疾病傳染的資料,檢驗 chemicals 可以知道這區的人都在幹麻,例如他們發現禮拜六和禮拜一早上的 sewage 裡面含大量的 Advil 和 Tylenol (就是台灣的普拿疼之類的)。(在場的大家都發出一種會心一笑的笑聲,我猜是因為週五和週日晚上喝太多酒,結果隔天頭痛所以吃止痛藥。)然後也可以靠這樣檢驗出 sewage 裡面是否有 opioid,這區的人用鴉片的人口多少之類的。

ps. 她有提到 Guelph 的便便重製機 RePoopulator 重製便便(repoopulate),話說研究重製便便的教授因為和我母校 Queen's 的教授合作,所以還有到本系的 seminar 演講,我是那時知道 repoopulate 的,有興趣的可以看這兩篇:

Nature / Faeces-filled pill stops gut infection (2013)

U of Guelph / Synthetic 'Poop' Can Cure C. difficile Infection, Study Finds

(標題感覺很聳動,好像是真的吃便便,但其實是和 pro-biotics 有關。)

最後一個影片是關於殺人鯨 Orca,因為溫哥華沿海的殺人鯨數量近幾年少很多,保育學專家想知道為什麼,所以要收集 Orca 的便便檢驗。他們收集的方法很有趣,用的是救生犬,他們訓練救生犬辨別 Orca 便便的味道,然後帶牠出海到海中充滿 Orca 的地方等鯨魚便便,鯨魚便便了以後大便會浮在海面上,救生犬聞到以後頭就會轉向便便的位置,船再開過去,當救生犬確定便便的位子後就會叫,然後研究員就可以把鯨魚的便便撈起來。好了,結果是什麼呢?他們分析發現是因為鮭魚變少了,不夠鯨魚吃,於是牠們出現營養不良的現象。

我覺得真的很有趣,很值得一看,明年上線以後一定要找來看啊~~

最後說一下小遊戲是什麼,遊戲叫 PowerPoint karaoke,就是主辦團體會準備好幾份 slides,每個主題都不同,重點是講者們答應了要上台報告了以後,主辦團當天才會給你 slides,也就是等講者上台了,主持人把 ppt 打開了以後,講者才知道自己要講的主題是什麼。但是因為 slides 的內容都是自己不懂的,所以就看你要在台上怎麼掰、掰功如何,笑果非常好,如果有人想辦活動又不知道要玩什麼遊戲,可以玩這個,很搞笑。XD


ps. 其實這是我第一次去 Nerd Night 的活動,因為最近才發現的。