像學(xué)R一樣學(xué)Python(高級(jí)數(shù)據(jù)管理)

溫故

在基本數(shù)據(jù)管理部分率挣,主要是涉及到如何新建數(shù)據(jù)集清寇,并且對(duì)數(shù)據(jù)集中的變量和觀測(cè)值進(jìn)行提取和操作∽隹基本上用到了如下函數(shù)占哟,可以根據(jù)函數(shù)名回憶一下用法:

import pandas as pd
import numpy as np
from pandas import Series, DataFrame
pd.read_table()
# 假設(shè)新建一個(gè)數(shù)據(jù)框?yàn)閐f
df.head(), df.tail(), df.shape(), df.dtypes()
df['var'] = values # 新建變量
np.where(), np.logical_and, np.less, np.greater # 變量重編碼
df.index, df.columns, df.index.map, df.columns.map, df.index.rename, df.index.reanme # 變量重命名
df.isnull, df.notnull, df.dropna, df,fillna #  缺失值處理
pd.to_datetime# 日期值
df.astype # 數(shù)據(jù)類型轉(zhuǎn)換
df.sorte_index df.sort.values # 排序
pd.merge, pd.concat, pd.appedn # 合并數(shù)據(jù)集
df.ix[], df[], df.loc[] # 數(shù)據(jù)取子集
df.sample # 抽樣

知新,一個(gè)實(shí)際案例

這一次我們使用R語言實(shí)戰(zhàn)高級(jí)數(shù)據(jù)管理的案例:

要討論數(shù)值和字符處理函數(shù)酿矢,讓我們首先考慮一個(gè)數(shù)據(jù)處理問題榨乎。一組學(xué)生參加了數(shù)學(xué)、科學(xué)和英語考試瘫筐。為了給所有學(xué)生確定一個(gè)單一的成績(jī)衡量指標(biāo)蜜暑,需要將這些科目的成績(jī)組合起來。另外策肝,你還想將前20%的學(xué)生評(píng)定為A肛捍,接下來20%的學(xué)生評(píng)定為B,依次類推之众。最后拙毫,你希望按字母順序?qū)W(xué)生排序。數(shù)據(jù)如表5-1所示棺禾。
觀察此數(shù)據(jù)集缀蹄,馬上可以發(fā)現(xiàn)一些明顯的障礙。首先,三科考試的成績(jī)是無法比較的袍患。由于它們的均值和標(biāo)準(zhǔn)差相去甚遠(yuǎn)坦康,所以對(duì)它們求平均值是沒有意義的。你在組合這些考試成績(jī)之前诡延,必須將其變換為可比較的單元滞欠。其次,為了評(píng)定等級(jí)肆良,你需要一種方法來確定某個(gè)學(xué)生在前述得分上百分比排名筛璧。再次,表示姓名的字段只有一個(gè)惹恃,這讓排序任務(wù)復(fù)雜化了夭谤。為了正確地將其排序,需要將姓和名拆開巫糙。

學(xué)生成績(jī)

如下介紹的函數(shù)大部分在Python自帶庫如math朗儒,內(nèi)置函數(shù)都有,但是都不是元素級(jí)別的参淹,也就是必須要寫一個(gè)顯性的循環(huán)函數(shù)醉锄,和numpy,pandas提供的相比效率相差1000倍以上浙值。

數(shù)學(xué)函數(shù)

數(shù)學(xué)函數(shù)主要由numpy提供恳不,避免用到Python的低效的內(nèi)置循環(huán),轉(zhuǎn)而使用C封裝高效的矢量化運(yùn)算开呐。用法都是np.func() 烟勋。

函數(shù) 描述
abs, fabs 絕對(duì)值。非復(fù)數(shù)值筐付,用fabs
sqrt 各元素的平方根
square 計(jì)算各元素的平方
exp 計(jì)算個(gè)元素的指數(shù)
log, log10, log2, log1p 對(duì)數(shù)運(yùn)算
sign 計(jì)算各元素的正負(fù)號(hào)
ceil(x) 不小于x的最小整數(shù)
floor(x) 不大于x的最小整數(shù)
rint(x) 將x四舍五入到最接近的整數(shù)卵惦,保留dtype
cos, sin, tan 余弦,正弦和正切
cosh, sinh, tanh 雙曲余弦家妆,雙曲正弦和雙曲正切
arccos, arcsin, arctan 反余弦鸵荠,反正弦和反正切
arccosh, arcsinh, arctanh 反雙曲余弦,反雙曲正弦和反雙曲正切

我們經(jīng)常會(huì)用到這些函數(shù)對(duì)數(shù)據(jù)進(jìn)行變換伤极。當(dāng)然蛹找,你可能已經(jīng)忘記了三角函數(shù)對(duì)應(yīng)是什么圖形了,這個(gè)時(shí)候就可以嘗試一下自己作圖了哨坪。

%matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
x = np.arange(-2*np.pi, 2*np.pi, 0.01*np.pi)
y = np.cos(x)
plt.plot(x,y)

更多有關(guān)的numpy的數(shù)學(xué)函數(shù)可以看官方文檔的2.8.1節(jié)庸疾。

統(tǒng)計(jì)函數(shù)

pandas對(duì)象擁有一組常用的數(shù)學(xué)和統(tǒng)計(jì)方法,比如說最大值当编,最小值届慈,均值,中位數(shù),四分位數(shù)等金顿。用法是df.func()臊泌。部分函數(shù)在numpy也有,因此是np.func揍拆。

方法 說明
desribe 列計(jì)算匯總渠概,列出四分位數(shù)等信息
max,min 最大值和最小值
idxmin, idxmax 最大值和最小值的索引位置
quantile 分位數(shù)
sum 求和
mean 平均數(shù)
median 中位數(shù)
mad 根據(jù)平均值計(jì)算平均離差
var 方差
std 標(biāo)準(zhǔn)差
skew 樣本值的偏度(三階矩)
kurt 樣本值的豐度(四階矩)
cumsum 樣本的累積和
cummin,cummax 累計(jì)最大值和最小值
cumprod 累積積
diff 計(jì)算一階差分
pct_change 計(jì)算百分比變化

簡(jiǎn)單案例:均值和標(biāo)準(zhǔn)差的計(jì)算

x = np.arange(1,10,1)
x.mean() # np.mean(x)
x.std() # np.std(x)

概率函數(shù)

根據(jù)定義嫂拴,概率函數(shù)也屬于統(tǒng)計(jì)類播揪,但是pandas沒有提供這類函數(shù)。這類函數(shù)用到一個(gè)專門的科學(xué)計(jì)算庫 scipy筒狠, 是一組專門解決科學(xué)計(jì)算中各種標(biāo)準(zhǔn)問題域的包的集合猪狈。

為了能更好的應(yīng)用,可能需要花一點(diǎn)功夫稍微講解一下 scipy 的 概率函數(shù)(stats)模塊辩恼。該模塊提供了常用的概率分布雇庙,大致分為兩類,連續(xù)型分布和離散型分布灶伊,這兩類分布都是 rv__continuousrv_discrete 的子類状共。

比如說標(biāo)準(zhǔn)的正態(tài)函數(shù)分布失尖,norm, 作為 rv_continuous的子類耸峭,它覆寫了父類的pdf方法

norm.pdf(x) = exp(-x**2/2)/sqrt(2*pi)

用人類更加可讀的形式寫出來就是 $f(x) = \frac{1}{\sqrt(2\pi)} e{-\frac{x2}{2}}$ 也就是教科書上的定義方式笋额。如果查看他的均值和方差,也是熟悉的0和1. 也就是說通過rv__continuousrv_discrete 這兩個(gè)父類還能夠構(gòu)造出 stats 模塊沒有提供分布函數(shù)匈挖。

子類繼承父類的方法,如 var, std, mean, median 提供分布的各統(tǒng)計(jì)量, expect 計(jì)算期望值康愤, stats 函數(shù)提供了moments參數(shù)用于指定需要計(jì)算的統(tǒng)計(jì)量儡循,m=mean, v=variance, s=Fisher's skew, k=Fisher's kurtosis.

R中的概率函數(shù)形如[dpqr] 分布函數(shù)英文縮寫,scipy.stats則是分布函數(shù)英文縮寫.方法

  • rvs(): 根據(jù)概率分布征冷,返回隨機(jī)數(shù)
  • pdf(x): 密度函數(shù)择膝, 對(duì)應(yīng)R的d
  • cdf(x): 給定隨機(jī)變量(RV)的累積分布函數(shù)(),對(duì)應(yīng)R的p
  • ppf(x): 分位數(shù)函數(shù)(quantile function) 對(duì)應(yīng)R的q
  • sf(x): 生存函數(shù)(1-cdf)

常用的概率函數(shù)如下表

連續(xù)型分布 縮寫 離散型分布 縮寫
Beta分布 beta 二項(xiàng)分布 binorm
柯西分布 cauchy 幾何分布 geom
卡方分布 chi2 超幾何分布 hypergeom
指數(shù)分布 expon 負(fù)二項(xiàng)分布 nbinom
F分布 f 泊松分布 poisson
(通用) Gmamma分布 (gen)gamma - -
對(duì)數(shù)正態(tài)分布 exponnorm - -
(通用)正態(tài)分布 (gen)nrom) - -

其他相關(guān)的分布用到的時(shí)候查官方文檔就行了。

以熟悉的正態(tài)分布的有關(guān)函數(shù)和方法為例检激,了解這些函數(shù)的使用方法肴捉。如標(biāo)準(zhǔn)正態(tài)函數(shù)的密度函數(shù)(norm.pdf),分布函數(shù)(norm.ppf)叔收,隨機(jī)數(shù)生成函數(shù)

繪制標(biāo)準(zhǔn)正態(tài)曲線

from scipy.stats import norm
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1)
x = np.linspace(-3,3,30) # 非常熟悉的MATLAB齿穗,對(duì)應(yīng)R的pretty
y = norm.pdf(x) # 對(duì)應(yīng)R的dnrom
ax.plot(x,y,'r-', lw=5, alpha=0.6, label='norm pdf')
正態(tài)分布

)

norm.cdf(1.96)約等于0.975, norm.ppf(0.975) 與等于1.96饺律。
norm.rvs(siez=(4,4))生成一個(gè)4X4的隨機(jī)數(shù)窃页,等同于np.random.normal(size=(4,4)).

字符處理函數(shù)

Python本身的字符處理模塊是非常多的,比如說re用于正則,string是常用字符操作模塊脖卖, 字符串?dāng)?shù)據(jù)類型本身還有許多方法乒省。 我在簡(jiǎn)書上的一篇文章Python與R的異同(二):字符串操作 就介紹了兩則的異同。

這些函數(shù)無法直接套用到ndarry畦木, Series, DataFrame數(shù)據(jù)結(jié)構(gòu)中袖扛,需要用到專門的方法。不過馋劈,pandas提供了矢量化的字符串方法攻锰,更加高效。

方法 說明
len 計(jì)算字符數(shù)量
contains 是否符合含指定模式的布爾型數(shù)組
count 最大值和最小值的索引位置
findall 計(jì)算各字符串的模式列表
cat 實(shí)現(xiàn)元素級(jí)的字符串連接操作
get 獲取第i個(gè)元素
lower, upper 大小寫轉(zhuǎn)換
match 元素級(jí)別的re.match
split 根據(jù)正則或指定分隔符進(jìn)行分割
strip, rstrip, lstrip 去除空白符妓雾,包括換行符
join 根據(jù)指定的分隔符進(jìn)行連接
repeat 對(duì)字符進(jìn)行重復(fù)
replace 用指定的字符串替換找到的模式

以《利用Python做數(shù)據(jù)分析》的數(shù)據(jù)為例娶吞,介紹如何匹配字符,提取指定內(nèi)容械姻。

data = {'Dava':'dave@google.com','Steve':'steve@gmail.com','Rob':'rob@gmail.com','Wes':np.nan}
data = Series(data)
data.str.contains('gmail')
import re
# 提取姓名等信息
pattern = re.compile(r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.[A-Z]{2,4}', flags=re.IGNORECASE)
data.str.findall(pattern)

將函數(shù)應(yīng)用到Series和DataFrame中

我們介紹的數(shù)學(xué)函數(shù)和統(tǒng)計(jì)函數(shù)妒蛇,大部分都是元素級(jí)別的操作,也就是能夠直接應(yīng)用到一系列數(shù)據(jù)結(jié)構(gòu)上楷拳,包括Python自帶的序列數(shù)據(jù)結(jié)構(gòu)绣夺,list, tuple, numpy的ndarray,pandas提供的Series和DataFrame.

a = 5
np.sqrt(a) # 如果用math.sqrt(5)欢揖,效率相差100倍
b = np.array([1.243,5.654,2.99])
np.round(b) # 比[round(x) for x in b] 快5倍
c = np.random.uniform(size=(3,4))
np.log(c)
np.mean(c)

默認(rèn)情況下陶耍,np.mean計(jì)算的是總體均值,如果你希望按行按列計(jì)算均值的話她混,可以簡(jiǎn)單的使用np.meanc(c, axis=1)烈钞,axis的0表示按列,1表示按行坤按。還有一個(gè)比較通用的方法類似于R的apply函數(shù)毯欣。

numpy使用的apply_along_axisapply_over_axes;pandas則是為數(shù)據(jù)框提供了applyapplymap方法. 這里演示pandas的apply方法, 其他查看幫助文檔就行臭脓。

# df.apply(func, axis=0), func可以是自定義函數(shù)
data = DataFrame(c)
data.apply(np.mean, 1)

除了apply外酗钞,pandas還允許用applymap映射原來的Python的自帶函數(shù)成為元素級(jí)函數(shù). 比如說直接用math.ceil(data)是不行的,需要用applymap進(jìn)行映射来累。

data.applymap(lambda x : math.ceil(x)) #相比較np.ceil 效率相差80倍

解決問題

還記得之前提出的問題嗎, 先回顧一下砚作,然后用剛才學(xué)到的知識(shí)進(jìn)行解決。

將學(xué)生的各科考試成績(jī)組合為單一的成績(jī)衡量指標(biāo)嘹锁、基于相對(duì)名次(前20%偎巢,下20%,等等)給出從A到F的評(píng)分兼耀、根據(jù)學(xué)生姓氏和名字的首字母對(duì)花名冊(cè)進(jìn)行排序

第一步: 數(shù)據(jù)輸入

# 導(dǎo)入庫
import numpy as np
from pandas import Series, Dataframe
# 數(shù)據(jù)
roster = pd.read_csv("student_grade.txt", header=None,names=["Student","Math","Science", "English"])

第二步: 計(jì)算綜合評(píng)分压昼。計(jì)算綜合得分就是先對(duì)每一門學(xué)科的成績(jī)進(jìn)行標(biāo)準(zhǔn)化求冷,然后進(jìn)行相加。標(biāo)準(zhǔn)化的一種方法是歸一化窍霞,即將一組數(shù)據(jù)進(jìn)行均值為0匠题,標(biāo)準(zhǔn)差為1的標(biāo)準(zhǔn)化。

score = np.mean(roster.ix[:,1:].apply(lambda x : (x-np.mean(x))/np.std(x)), axis=1)
roster['score'] = score

這一步比較復(fù)雜的就是我用了匿名函數(shù)進(jìn)行標(biāo)準(zhǔn)化但金,然后用np.mean進(jìn)行計(jì)算均值韭山。

第三步: 計(jì)算四分位數(shù), 并且學(xué)生進(jìn)行評(píng)分

y = roster.score.quantile(q=[0.8,0.6,0.4,0.2])
grade = np.where(score > y.ix[0.8], 'A', np.where(score > y.ix[0.6], 'B', np.where(score > y.ix[0.4], 'D','F')))
roster['grade'] = grade

這一步用到了np.where進(jìn)行元素級(jí)別的判斷。冷溃、復(fù)制給grade列钱磅。

第四步: 根據(jù)學(xué)生姓氏和名字的首字母對(duì)花名冊(cè)進(jìn)行排序

first_name = roster.Student.apply(lambda x: x.split(sep=' ')[0])
last_name = roster.Student.apply(lambda x: x.split(sep=' ')[1])
roster['first_name'] = firt_name
roster['last_name'] = last_name
roster.drop('Student', axis=1, inplace=True)

同樣用到了匿名函數(shù), 對(duì)所有元素應(yīng)用字符處理函數(shù)似枕。

第五步: 排序

roster.sort_values(by=['first_name','last_name'], inplace=True)

最后結(jié)果如下:

結(jié)果示意
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盖淡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凿歼,更是在濱河造成了極大的恐慌褪迟,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件答憔,死亡現(xiàn)場(chǎng)離奇詭異味赃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)虐拓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門心俗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蓉驹,你說我怎么就攤上這事另凌。” “怎么了戒幔?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)土童。 經(jīng)常有香客問我诗茎,道長(zhǎng),這世上最難降的妖魔是什么献汗? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任敢订,我火速辦了婚禮,結(jié)果婚禮上罢吃,老公的妹妹穿的比我還像新娘楚午。我一直安慰自己,他們只是感情好尿招,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布矾柜。 她就那樣靜靜地躺著阱驾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怪蔑。 梳的紋絲不亂的頭發(fā)上里覆,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音缆瓣,去河邊找鬼喧枷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛弓坞,可吹牛的內(nèi)容都是我干的隧甚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼渡冻,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼戚扳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起菩帝,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤咖城,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后呼奢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宜雀,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年握础,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辐董。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡禀综,死狀恐怖简烘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情定枷,我是刑警寧澤孤澎,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站欠窒,受9級(jí)特大地震影響覆旭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岖妄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一型将、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荐虐,春花似錦七兜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惜犀。三九已至,卻和暖如春恬惯,著一層夾襖步出監(jiān)牢的瞬間向拆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工酪耳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浓恳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓碗暗,卻偏偏與公主長(zhǎng)得像颈将,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子言疗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容