三甸私、Python 編程
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
編程可以極大地提高我們收集和分析世界信息的能力诚些,而這些信息又可以通過上一節(jié)所述的謹慎推理來發(fā)現。 在數據科學中皇型,編寫程序的目的是诬烹,指示計算機執(zhí)行分析步驟。 電腦無法自行研究世界弃鸦。 人們必須準確描述計算機應該執(zhí)行什么步驟來收集和分析數據绞吁,這些步驟是通過程序來表達的。
表達式
編程語言比人類語言簡單得多唬格。 盡管如此家破,在任何語言中,還是有一些語法規(guī)則需要學習购岗,這里就是我們開始的地方汰聋。 在本文中,我們將使用 Python 編程語言喊积。 學習語法規(guī)則是必不可少的烹困,最基本的程序中使用的規(guī)則也是更復雜程序的核心。
程序由表達式組成注服,向計算機描述了如何組合數據片段韭邓。 例如措近,乘法表達式由兩個數字表達式之間的*
符號組成。表達式女淑,例如3*4
瞭郑,由計算機求值。在這種情況下鸭你,(IPython 中的)每個單元格中的最后一個表達式的值(求值結果)將顯示在單元格下方屈张,這里是 12。
3 * 4
12
編程語言的語法規(guī)則是僵化的袱巨。 在 Python 中阁谆,*
符號不能連續(xù)出現兩次。 計算機不會試圖解釋一個與規(guī)定的表達式結構不同的表達式愉老。 相反场绿,它會顯示SyntaxError
錯誤。 語言的語法是其語法規(guī)則的集合嫉入,SyntaxError
表示表達式結構不匹配任何語法規(guī)則焰盗。
3 * * 4
File "<ipython-input-4-d90564f70db7>", line 1
3 * * 4
^
SyntaxError: invalid syntax
表達式的小改動可以完全改變它的含義。 下面咒林,*
之間的空格已被刪除熬拒。 因為**
出現在兩個數字表達式之間,所以表達式是一個格式良好的指數表達式(第一個數字的第二個數字次方垫竞,3*3*3*3
)澎粟。 符號*
和**
稱為運算符,它們組合的值稱為操作數欢瞪。
3 ** 4
81
常用操作符活烙。 數據科學通常涉及數值的組合,而編程語言中的一組操作符引有,是為了使得表達式可以用于表示任何類型的算術瓣颅。 在Python中,以下操作符是必不可少的譬正。
表達式類型 | 運算符 | 示例 | 值 |
---|---|---|---|
加法 | + |
2 + 3 |
5 |
減法 | - |
2 - 3 |
-1 |
乘法 | * |
2 * 3 |
6 |
除法 | / |
7 / 3 |
2.66667 |
取余 | % |
7 % 3 |
1 |
指數 | ** |
2 ** 0.5 |
1.41421 |
Python 表達式遵循熟悉的優(yōu)先級規(guī)則宫补,與代數中相同:乘法和除法在加法和減法之前計算。 圓括號可以用來在較大的表達式中曾我,將較小的表達式組合在一起粉怕。
1 + 2 * 3 * 4 * 5 / 6 ** 3 + 7 + 8 - 9 + 10
17.555555555555557
1 + 2 * (3 * 4 * 5 / 6) ** 3 + 7 + 8 - 9 + 10
2017.0
示例
這里是一個圖表,來自 20 世紀 80 年代初期的“華盛頓郵報”(The Washington Post)抒巢,試圖比較幾十年來醫(yī)生的收入與其他專業(yè)人員的收入贫贝。 我們是否真的需要在每個條形上看到兩個頭(一個帶有聽診器)? 耶魯大學教授愛德華·圖夫特(Edward Tufte)是世界上量化信息可視化的專家之一,他為這種不必要的修飾創(chuàng)造了“垃圾圖表”(chartjunk)一詞稚晚。 這張圖也是 Tufte 痛恨的“數據與油墨比例過低”的一個例子崇堵。
華盛頓郵報圖片
最重要的是,圖的橫軸不是按比例繪制的。 這對條形圖的形狀有顯著的影響。 當按規(guī)模繪制并把裝飾修剪掉時编兄,圖表顯示的趨勢非常不同于原來明顯的線性增長。 下面的優(yōu)雅圖表由統(tǒng)計系統(tǒng) R 的創(chuàng)始人之一 Ross Ihaka 提供赏廓。
Ross Ihaka 的圖片版本
在 1939 年到 1963 年間,醫(yī)生的收入從 3,262 美元增加到 25,050 美元傍妒。 所以在這個時期幔摸,每年的平均收入增加了大約 900 美元。
(25050 - 3262)/(1963 - 1939)
907.8333333333334
在 Ross Ihaka 的圖表中可以看到颤练,在這個時期既忆,醫(yī)生的收入大致呈線性上升,并且保持在一個相對穩(wěn)定的水平嗦玖。 正如我們剛剛計算的那樣尿贫,這個比率大約是 900 美元。
但是從 1963 年到 1976 年踏揣,這個比例是三倍多:
(62799 - 25050)/(1976 - 1963)
2903.769230769231
這就是 1963 年之后,這個圖形急劇上升的原因匾乓。
本章介紹了許多類型的表達式捞稿。 學習編程需要結合學到所有的東西,調查計算機的行為拼缝。 如果你連續(xù)除兩次會發(fā)生什么娱局? 你并不需要總是問專家(或互聯(lián)網);許多這些細節(jié)可以通過自己嘗試發(fā)現咧七。
數值
整數值
計算機為執(zhí)行數值計算而設計衰齐,但是關于處理數字有一些重要的細節(jié),每個處理定量數據的程序員都應該知道它继阻。 Python(和大多數其他編程語言)區(qū)分兩種不同類型的數字:
- 整數在 Python 語言中稱為
int
值耻涛。 它們只能表示沒有小數部分的整數(負數,零或正數) - 實數在 Python 語言中被稱為
float
值(或浮點值)瘟檩。 他們可以表示全部或部分數字抹缕,但有一些限制。
數值的類型在展示方式上是明顯的:int
值沒有小數點墨辛,float
值總是有一個小數點卓研。
# Some int values
2
2
1 + 3
4
-1234567890000000000
-1234567890000000000
# Some float values
1.2
1.2
1.5 + 2
3.5
3 / 1
3.0
-12345678900000000000.0
-1.23456789e+19
當一個float
值和一個int
值,通過算術運算符組合在一起時,結果總是一個float
值奏赘。 在大多數情況下寥闪,兩個整數的組合形成另一個整數,但任何數字(int
或float
)除以另一個將是一個float
值磨淌。 非常大或非常小的float
值可以使用科學記數法表示疲憋。
浮點值
浮點值非常靈活,但他們有限制伦糯。
float
可以表示非常大和非常小的數字柜某。存在限制,但你很少遇到他們敛纲。
浮點數只能表示任何數字的 15 或 16 位有效數字喂击;剩下的精度就會丟失。 這個有限的精度對于絕大多數應用來說已經足夠了淤翔。
將浮點值與算術運算結合后翰绊,最后的幾位數字可能不正確。 第一次遇到時旁壮,微小的舍入錯誤往往令人困惑监嗜。
第一個限制可以通過兩種方式來觀察。 如果一個計算的結果是一個非常大的數字抡谐,那么它被表示為無限大裁奇。 如果結果是非常小的數字,則表示為零麦撵。
2e306 * 10
2e+307
2e306 * 100
inf
2e-322 / 10
2e-323
2e-322 / 100
0.0
第二個限制可以通過涉及超過 15 位有效數字的表達式來觀察刽肠。 在進行任何算術運算之前,這些額外的數字被丟棄免胃。
0.6666666666666666 - 0.6666666666666666123456789
0.0
當兩個表達式應該相等時音五,可以觀察到第三個限制。 例如羔沙,表達式2 ** 0.5
計算 2 的平方根躺涝,但是該值的平方不會完全恢復成 2。
2 ** 0.5
1.4142135623730951
(2 ** 0.5) * (2 ** 0.5)
2.0000000000000004
(2 ** 0.5) * (2 ** 0.5) - 2
4.440892098500626e-16
上面的最終結果是0.0000000000000004440892098500626
扼雏,這個數字非常接近零坚嗜。 這個算術表達式的正確答案是 0,但是最后的有效數字中的一個小錯誤呢蛤,在科學記數法中顯得非常不同惶傻。 這種行為幾乎出現在所有的編程語言中,因為它是在計算機上進行算術運算的標準方式的結果其障。
盡管float
并不總是精確的银室,但它們當然是可靠的,并且在所有不同種類的計算機和編程語言中,以相同的方式工作蜈敢。
名稱
名稱通過賦值語句在 Python 中得到一個值辜荠。 在賦值中,名稱后面是=
抓狭,再后面是任何表達式伯病。 =
右邊的表達式的值被賦給名稱。 一旦名稱有了賦給它的值否过,在將來的表達式中午笛,值會替換為這個名稱。
a = 10
b = 20
a + b
30
之前賦值的名稱可以在=
右邊的表達式中使用苗桂。
quarter = 1/4
half = 2 * quarter
half
0.5
但是药磺,僅僅是表達式的當前值賦給了名稱。 如果該值稍后改變煤伟,則由該值定義的名稱將不會自動更改癌佩。
quarter = 4
half
0.5
名稱必須以字母開頭,但可以包含字母和數字便锨。 名稱不能包含空格围辙;相反,通常使用下劃線字符_
來替換每個空格放案。名稱只在你編寫的時候是有用的姚建;程序員可以選擇易于理解的名稱。 通常吱殉,比起a
和b
桥胞,你可以創(chuàng)造更有意義的名字。 例如考婴,為了描述加利福尼亞州伯克利 5 美元商品的銷售稅,以下名稱闡明了各種相關數量的含義催烘。
purchase_price = 5
state_tax_rate = 0.075
county_tax_rate = 0.02
city_tax_rate = 0
sales_tax_rate = state_tax_rate + county_tax_rate + city_tax_rate
sales_tax = purchase_price * sales_tax_rate
sales_tax
0.475
示例:增長率
相同數量在不同時間取得的兩次測量值之間的關系通常表示為增長率沥阱。 例如,美國聯(lián)邦政府在 2002 年雇用了 276.6 萬人伊群,在 2012 年雇用了 281.4 萬人考杉。為了計算增長率,我們必須首先決定將哪個值作為初始值舰始。 對于隨著時間變化的數值崇棠,較早的值是一個自然的選擇。 然后丸卷,我們將變動值和初始值之間的差除以初始值枕稀。
initial = 2766000
changed = 2814000
(changed - initial) / initial
0.01735357917570499
通常從兩個測量值的比例中減去 1,這產生相同的值。
(changed/initial) - 1
0.017353579175704903
這個值是 10 年間的增長率萎坷。 增長率的一個實用屬性是凹联,即使值以不同的單位表示,它們也不會改變哆档。 所以蔽挠,例如,我們可以以千人為單位瓜浸,在 2002 年和 2012 年之間表達同樣的關系澳淑。
initial = 2766
changed = 2814
(changed/initial) - 1
0.017353579175704903
10 年以來,美國聯(lián)邦政府的雇員人數僅增長了 1.74%插佛。 那個時候杠巡,美國聯(lián)邦政府的總支出從 2.37 萬億美元增加到 2012 年的 3.38 萬億美元。
initial = 2.37
changed = 3.38
(changed/initial) - 1
0.4261603375527425
聯(lián)邦預算增長 42.6% 遠高于聯(lián)邦雇員增長 1.74%朗涩。 實際上忽孽,聯(lián)邦雇員的數量增長速度遠遠低于美國人口。美國人口同期增長 9.21%谢床,從 2002 年的 2.8760 億人增加到 2012 年的 3.41 億兄一。
initial = 287.6
changed = 314.1
(changed/initial) - 1
0.09214186369958277
增長率可能是負值,表示某種值的下降识腿。 例如出革,美國的制造業(yè)就業(yè)崗位從 2002 年 的 1530 萬減少到 2012 年的 1190 萬,增長率為 -22.2%渡讼。
initial = 15.3
changed = 11.9
(changed/initial) - 1
-0.2222222222222222
年增長率是一年之內的某個數量的增長率骂束。 年增長率為 0.035,累計十年成箫,十年增長率為 0.41(即 41%)展箱。
1.035 * 1.035 * 1.035 * 1.035 * 1.035 * 1.035 * 1.035 * 1.035 * 1.035 * 1.035 - 1
0.410598760621121
相同的計算可以使用名稱和指數表達。
annual_growth_rate = 0.035
ten_year_growth_rate = (1 + annual_growth_rate) ** 10 - 1
ten_year_growth_rate
0.410598760621121
同樣蹬昌,十年的增長率可以用來計算等價的年增長率混驰。 下面,t
是兩次測量值之間經過的年數皂贩。 下面計算過去 10 年聯(lián)邦支出的年增長率栖榨。
initial = 2.37
changed = 3.38
t = 10
(changed/initial) ** (1/t) - 1
0.03613617208346853
十年來的總增長率相當于每年增長 3.6%。
總之明刷,增長率g
用來描述initial
(初始值)和經過一段時間t
之后的changed
(變化值)的相對大小婴栽。 為了計算changed
,使用指數來重復應用增長率g
t
次辈末。
initial * (1 + g) ** t
為了計算g
愚争,計算總增長率的1/t
次方并減一映皆。
(changed/initial) ** (1/t) - 1
調用表達式
調用表達式調用函數,這些函數是具名操作准脂。 函數名稱首先出現劫扒,然后是括號中的表達式。
abs(-12)
12
round(5 - 1.3)
4
max(2, 2 + 3, 4)
5
在這最后一個例子中狸膏,max
函數在三個參數:2
, 5
和4
上調用沟饥。圓括號內每個表達式的值被傳遞給函數,函數返回整個調用表達式的最終值湾戳。 max
函數可以接受任意數量的參數并返回最大值贤旷。
一些函數默認是可用的,比如abs
和round
砾脑,但是大部分內置于 Python 語言的函數都存儲在一個稱為模塊的函數集合中幼驶。 導入語句用于訪問模塊,如math
或operator
韧衣。
import math
import operator
math.sqrt(operator.add(4, 5))
3.0
可以使用+
和**
運算符來表達等價的表達式盅藻。
(4 + 5) ** 0.5
3.0
運算符和調用表達式可以在表達式中一起使用。 兩個值之間的百分比差異用于比較一些值畅铭,它們明顯既不是initial
也不是changed
氏淑。 例如,2014 年硕噩,佛羅里達農場生產了 27.2 億個蛋假残,而愛荷華州農場生產了 162.5 億個雞蛋 [1]。 百分比差值是數值之差的絕對值的 100 倍炉擅,再除以它們的平均值辉懒。 在這種情況下,差值大于平均值谍失,所以百分比差異大于 100眶俩。
florida = 2.72
iowa = 16.25
100*abs(florida-iowa)/((florida+iowa)/2)
142.6462836056932
學習不同函數的行為,是學習編程語言的重要組成部分快鱼。 Jupyter 筆記本可以幫助你記住不同函數的名稱和效果仿便。 編輯代碼單元格時,在輸入名稱的開頭之后按 Tab 鍵攒巍,來顯示補全該名稱的方式列表。 例如荒勇,在math
后按 Tab 鍵柒莉,來查看math
模塊中所有可用函數。 打字將縮小選項列表的范圍沽翔。 為了了解函數的更多信息兢孝,請在它的名稱之后放置一個?
窿凤。 例如跨蟹,輸入math.log
將顯示math
模塊中log
函數的描述夯秃。
math.log?
log(x[, base])
Return the logarithm of x to the given base.
If the base not specified, returns the natural logarithm (base e) of x.
示例調用中的方括號表示參數是可選的色建。 也就是說国撵,可以用一個或兩個參數來調用log
走越。
math.log(16, 2)
4.0
math.log(16)/math.log(2)
4.0
Python 的內建函數列表非常長谆构,包含了許多在數據科學應用中不需要的函數熬尺。 math
模塊中的數學函數列表同樣很長揭措。 本文將在上下文中介紹最重要的函數躬充,而不是期望讀者記住或理解這些列表麻裳。
示例
1869 年口蝠,一位名叫查爾斯·約瑟夫·米納德(Charles Joseph Minard)的法國土木工程師,創(chuàng)造了一個圖表津坑,仍被認為是有史以來最偉大的圖表之一妙蔗。 它顯示了拿破侖軍隊從莫斯科撤退期間的損失。 1812 年疆瑰,拿破侖開始征服俄羅斯眉反,他的軍隊中有超過 35 萬人。 他們確實到達了莫斯科穆役,但是沿路一直受到損失的困擾寸五。 俄國軍隊不斷撤退到俄羅斯深處,故意焚燒田野耿币,并在撤退時摧毀村莊梳杏。 這使法國軍隊在俄羅斯冬季來臨之時,沒有食物或避難所淹接。法國軍隊在莫斯科沒有取得決定性的勝利就撤退了十性。 之后天氣變冷,死了更多的人塑悼。 回來的人還不到一萬劲适。
Minard 的地圖
這個圖表繪制在東歐地圖上。 它始于左端的波蘭-俄羅斯邊界厢蒜。 淺棕色的條形表示拿破侖的軍隊正在向莫斯科進軍霞势,黑色的條形代表軍隊的撤退。 在圖表的每個點上斑鸦,軍隊的寬度與軍隊中士兵的數量成正比愕贡。在圖表的底部,Minard 包括了回程的溫度巷屿。
注意當軍隊撤退時固以,黑色條形變窄。 渡過貝爾齊納河是個特別的災難攒庵,你能在圖表上看到嗎嘴纺?
由于其簡單和有力,這個圖標是出色的浓冒。 Minard 展示了六個變量:
- 士兵的數量
- 行軍的方向
- 位置的經緯度
- 回程的溫度
- 十一月和十二月的具體日期的位置
Tufte 說 Minard 的圖是“可能是有史以來最好的統(tǒng)計圖表”栽渴。
這里是 Minard 數據的一個子集,取自 Leland Wilkinson 的 The Grammar of Graphics稳懒。
Minard 的子集
每一行表示特定位置的軍隊狀態(tài)闲擦。 列以度為單位展示經度和緯度,位置的名稱场梆,軍隊是前進還是撤退墅冷,以及估計的人數。
在這個表格中或油,連續(xù)兩個地點之間的人數的最大變化是在莫斯科撤退的時候寞忿,也是最大的百分比變化。
moscou = 100000
wixma = 55000
wixma - moscou
-45000
(wixma - moscou)/moscou
-0.45
在莫斯科的戰(zhàn)斗中顶岸,人數下降了 45%腔彰。 換句話說,進入莫斯科的拿破侖的軍隊中辖佣,有幾乎一半的人沒有繼續(xù)前進霹抛。
正如你在圖表中看到的,Moiodexno 非常接近軍隊出發(fā)位置 Kowno卷谈。 在前進期間進入 Smolensk 的人中杯拐,只有不到 10% 的人在返回的途中到達了 Moiodexno。
smolensk_A = 145000
moiodexno = 12000
(moiodexno - smolensk_A)/smolensk_A
-0.9172413793103448
是的世蔗,只要使用沒有名稱的數字就可以做這些計算端逼。 但是這些名稱使得閱讀代碼和解釋結果變得更容易。
值得注意的是凸郑,更大的絕對變化并不總是對應更大的百分比變化裳食。
在前進期間,從 Smolensk 到 Dorogobouge 的絕對損失是 5000 人芙沥,而撤退期間诲祸,從 Smolensk 到 Orscha 的相應損失是 4000 人。
然而而昨,Smolensk 和 Orscha 之間的百分比變化要大得多救氯,因為,在撤退期間歌憨,Smolensk 的人員總數要小得多着憨。
dorogobouge = 140000
smolensk_R = 24000
orscha = 20000
abs(dorogobouge - smolensk_A)
5000
abs(dorogobouge - smolensk_A)/smolensk_A
0.034482758620689655
abs(orscha - smolensk_R)
4000
abs(orscha - smolensk_R)/smolensk_R
0.16666666666666666