Python數(shù)據(jù)分析基礎(chǔ)

注意:本文是根據(jù)b站視頻總結(jié)的筆記,原視頻在這里

matplotlib部分

matplotlib主要用于畫圖束亏。

1. 先從一個簡單的代碼開始

我們收集了某城市某天內(nèi)每隔2小時的氣溫值铃在,準備畫出一天氣溫變化圖。

from matplotlib import pyplot as plt

x = range(2, 26, 2)  # x軸數(shù)據(jù)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]  # y軸數(shù)據(jù)
plt.plot(x, y)  # 傳入x和y枪汪,繪制折線圖
plt.show()  # 展示圖形

運行結(jié)果如下圖:

默認運行效果

可以發(fā)現(xiàn)圖已經(jīng)畫出來了涌穆,但是有時候這并不是我們想要的成品圖,我們希望能對他進行一些個性化的操作雀久。

2. 對圖片進行一些調(diào)整

(1)設(shè)置圖形大小

plt.figure(figsize=(20, 8), dpi=80)

如果覺得圖片太小了,可以用上面的代碼趁舀,設(shè)置長寬和dpi赖捌。

(2)調(diào)整坐標軸刻度

plt.xticks(ticks, labels)

常見用法如上。第一個參數(shù)ticks傳遞一個數(shù)組矮烹,通常直接傳遞x即可越庇。第二個參數(shù)labels也是一個數(shù)組,且長度與x一般相同奉狈,用于對ticks中對應(yīng)元素進行替換卤唉。例如在上面簡單的代碼中,加入如下內(nèi)容:

from matplotlib import pyplot as plt

x = range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]

plt.figure(figsize=(12, 8), dpi=80)
plt.xticks(x)  # 只傳入第一個參數(shù)

plt.plot(x, y)
plt.show()

顯示結(jié)果如下:

xticks只傳入一個參數(shù)

可以看到x軸的坐標已經(jīng)按照x的值顯示出來了仁期。但是顯示的只是數(shù)字桑驱,如果能顯示“2點”,“4點”這樣跛蛋,會更加直觀熬的,這就需要用到第二個參數(shù)。將代碼改成下面這樣:

from matplotlib import pyplot as plt

x = range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
x_ticks = ["{} o'clock".format(i) for i in x]

plt.figure(figsize=(12, 8), dpi=80)
plt.xticks(x, x_ticks)  # 傳入兩個參數(shù)赊级,將x軸的值和字符對應(yīng)起來

plt.plot(x, y)
plt.show()

顯示結(jié)果如下:

xticks傳入兩個參數(shù)

這樣一來押框,x軸的效果就很好了。但是y軸還是可以再改一下理逊。由于我們沒有設(shè)置y軸橡伞,因此系統(tǒng)默認為我們生成了一個盒揉。但是由于間隔為2,我們現(xiàn)在并不能很好的讀取每一個點的值兑徘,希望能把y軸間隔弄小一點预烙。同理,使用plt.yticks即可道媚。

from matplotlib import pyplot as plt

x = range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
x_ticks = ["{} o'clock".format(i) for i in x]

plt.figure(figsize=(12, 8))
plt.xticks(x, x_ticks)
plt.yticks(range(min(y), max(y) + 1))  # 根據(jù)y的值域顯示y軸刻度

plt.plot(x, y)
plt.show()

顯示效果如下:

更改y軸刻度

(3)增加網(wǎng)格

為了更加清楚的展示每個點的位置扁掸,我們可以為圖形添加網(wǎng)格:

plt.grid()

添加網(wǎng)格后效果如下:

添加網(wǎng)格

(4)添加圖形的描述并顯示中文

接下來我們?yōu)閳D形增加坐標軸描述和標題:

plt.xlabel("時間")
plt.ylabel("溫度:攝氏度")
plt.title("某地一天氣溫變化折線圖")

如果直接增加這些代碼,運行程序最域,會發(fā)現(xiàn)圖雖然能顯示出來谴分,但是所有的漢字都變成了框框,而且python還報了一堆錯镀脂。這主要是由于默認字體中不含中文字符造成的牺蹄。我們可以手動修改字體,顯示中文薄翅。

方法一:全局設(shè)置

import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="12")

方法二:分內(nèi)容設(shè)置

from matplotlib import font_manager

my_font = font_manager.FontProperties(fname="/usr/share/fonts/adobe-source-han-sans/SourceHanSansCN-Regular.otf")

plt.xlabel("時間", fontproperties=my_font)
plt.ylabel("溫度:攝氏度", fontproperties=my_font)
plt.title("某地一天氣溫變化折線圖", fontproperties=my_font)

我們采用全局設(shè)置沙兰,并將標題加粗,字號調(diào)大翘魄,修改完的代碼如下:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="12")

x = range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
x_ticks = ["{}點".format(i) for i in x]

plt.figure(figsize=(12, 8))
plt.grid()
plt.xticks(x, x_ticks)
plt.yticks(range(min(y), max(y) + 1))

plt.xlabel("時間")
plt.ylabel("溫度:攝氏度")
plt.title("某地一天氣溫變化折線圖", weight="bold", size="16")

plt.plot(x, y)
plt.show()

最后效果如圖:

增加描述并設(shè)置中文

(5)保存圖形

到這里基本的效果已經(jīng)有了鼎天,除了直接輸出圖片,還可以保存圖片:

plt.savefig(path)

這里可以保存為png格式暑竟,也可以保存為svg格式斋射,按需求來就行。注意但荤,plt.savefig()必須在畫圖之后在能保存罗岖,即應(yīng)放在plt.plot()的后面。

3. 常見的圖形的畫法

(1)折線圖

plt.plot(x, y, label, color, linestyle, ...)

案例:

畫出兩個人從11歲至30歲每年交女朋友的數(shù)量變化圖
a = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]
b = [1,0,3,1,2,2,3,3,2,1 ,2,1,1,1,1,1,1,1,1,1]

分析:

在同一幅圖中畫兩條折線腹躁,只需要使用plot方法兩次即可桑包,同時為每一條線設(shè)置標簽。

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="12")

x = range(11, 31)
y1 = [1, 0, 1, 1, 2, 4, 3, 2, 3, 4, 4, 5, 6, 5, 4, 3, 3, 1, 1, 1]
y2 = [1, 0, 3, 1, 2, 2, 3, 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
x_ticks = ["{}歲".format(i) for i in x]

plt.figure(figsize=(12, 8))
plt.grid(alpha=0.4)  # 設(shè)置網(wǎng)格透明度
plt.xticks(x, x_ticks)

plt.xlabel("年齡")
plt.ylabel("女朋友數(shù)量")
plt.title("A和B從11歲至30歲女朋友數(shù)量變化圖", weight="bold", size="16")

plt.plot(x, y1, label="A同學", color="#F08080")
plt.plot(x, y2, label="B同學", color="#DB7093", linestyle="--")
plt.legend()  # 顯示圖例
plt.show()

效果:

折線圖

(2)散點圖

plt.scatter(x, y, label, ...)

案例:

畫出三月和十月每天氣溫的變化散點圖

y3 = [11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23]

y10 = [26,26,28,19,21,17,16,19,18,20,20,19,22,23,17,20,21,20,22,15,11,15,5,13,17,10,11,13,12,13,6]

分析:

通過控制x將兩個散點圖畫在同一張圖里,便于比較

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="12")

x3 = range(1, 32)
y3 = [
    11, 17, 16, 11, 12, 11, 12, 6, 6, 7, 8, 9, 12, 15, 14, 17, 18, 21, 16, 17,
    20, 14, 15, 15, 15, 19, 21, 22, 22, 22, 23
]
x10 = range(41, 72)
y10 = [
    26, 26, 28, 19, 21, 17, 16, 19, 18, 20, 20, 19, 22, 23, 17, 20, 21, 20, 22,
    15, 11, 15, 5, 13, 17, 10, 11, 13, 12, 13, 6
]

x = list(x3) + list(x10)
x_ticks = ["3月{}日".format(i) for i in x3] + ["10月{}日".format(i - 40) for i in x10]

plt.figure(figsize=(15, 10))
plt.xticks(x[::3], x_ticks[::3], rotation=45)

plt.xlabel("日期")
plt.ylabel("溫度:攝氏度")
plt.title("三月和十月每天氣溫的變化散點圖", weight="bold", size="16")

plt.scatter(x3, y3, label="三月", color="orange")
plt.scatter(x10, y10, label="十月", color="cyan")
plt.legend()
plt.show()

這里有兩個點值得注意。第一個是通過控制x的范圍將兩個散點圖在同一張圖上分開顯示绪励,第二個就是對于x軸刻度的控制。因為如果31天全都寫出來垒手,會顯得非常擠,所以在用plt.xticks做對應(yīng)的時候倒信,每隔3天對應(yīng)一次科贬,這樣中間未對應(yīng)的值就不會顯示了,同時還將文本旋轉(zhuǎn)45度便于查看榜掌。

效果:

散點圖

(3)條形圖

plt.bar(x, y, width)  # 縱向條形圖
plt.barh(x, y, height)  # 橫向條形圖

I. 縱向條形圖

案例:

畫出2017年電影票房的條形圖

a = ["戰(zhàn)狼2","速度與激情8","功夫瑜伽","西游伏妖篇","變形金剛5:最后的騎士","摔跤吧优妙!爸爸","加勒比海盜5:死無對證","金剛:骷髏島","極限特工:終極回歸","生化危機6:終章","乘風破浪","神偷奶爸3","智取威虎山","大鬧天竺","金剛狼3:殊死一戰(zhàn)","蜘蛛俠:英雄歸來","悟空傳","銀河護衛(wèi)隊2","情圣","新木乃伊"]

b = [56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="10")

x_ticks = [
    "戰(zhàn)狼2", "速度與激情8", "功夫瑜伽", "西游伏妖篇", "變形金剛5:最后的騎士", "摔跤吧!爸爸", "加勒比海盜5:死無對證",
    "金剛:骷髏島", "極限特工:終極回歸", "生化危機6:終章", "乘風破浪", "神偷奶爸3", "智取威虎山", "大鬧天竺",
    "金剛狼3:殊死一戰(zhàn)", "蜘蛛俠:英雄歸來", "悟空傳", "銀河護衛(wèi)隊2", "情圣", "新木乃伊"
]
x = range(len(x_ticks))
y = [
    56.01, 26.94, 17.53, 16.49, 15.45, 12.96, 11.8, 11.61, 11.28, 11.12, 10.49,
    10.3, 8.75, 7.55, 7.32, 6.99, 6.88, 6.86, 6.58, 6.23
]

plt.figure(figsize=(15, 10))
plt.xticks(x, x_ticks, rotation=45)

plt.xlabel("電影名稱")
plt.ylabel("票房:億元")
plt.title("2017年電影票房條形圖", weight="bold", size="16")

plt.bar(x, y, 0.5)
plt.show()

效果:

縱向條形圖

我們發(fā)現(xiàn)由于名稱太長憎账,即便旋轉(zhuǎn)之后仍然難以閱讀套硼,故考慮使用橫向條形圖。

II. 橫向條形圖

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="10")

y_ticks = [
    "戰(zhàn)狼2", "速度與激情8", "功夫瑜伽", "西游伏妖篇", "變形金剛5:最后的騎士", "摔跤吧胞皱!爸爸", "加勒比海盜5:死無對證",
    "金剛:骷髏島", "極限特工:終極回歸", "生化危機6:終章", "乘風破浪", "神偷奶爸3", "智取威虎山", "大鬧天竺",
    "金剛狼3:殊死一戰(zhàn)", "蜘蛛俠:英雄歸來", "悟空傳", "銀河護衛(wèi)隊2", "情圣", "新木乃伊"
]
y = range(len(y_ticks))
x = [
    56.01, 26.94, 17.53, 16.49, 15.45, 12.96, 11.8, 11.61, 11.28, 11.12, 10.49,
    10.3, 8.75, 7.55, 7.32, 6.99, 6.88, 6.86, 6.58, 6.23
]

plt.figure(figsize=(15, 10))
plt.yticks(y, y_ticks)

plt.xlabel("票房:億元")
plt.ylabel("電影名稱")
plt.title("2017年電影票房條形圖", weight="bold", size="16")

plt.barh(y, x, 0.5)
plt.show()

效果:

橫向條形圖

我們發(fā)現(xiàn)在使用橫向條形圖的效果比縱向要好邪意。不過要注意的是,在繪制橫向條形圖時反砌,雖然圖上x軸和y軸的相對位置沒有變化雾鬼,但是plt.barh()方法是先傳y,再傳x的宴树。

III. 多個條形圖

案例:

展示幾部電影連續(xù)幾天票房的對比情況

a = ["猩球崛起3:終極之戰(zhàn)","敦刻爾克","蜘蛛俠:英雄歸來","戰(zhàn)狼2"]

b1 = [2358,399,2358,362]

b2 = [12357,156,2045,168]

b3 = [15746,312,4497,319]

分析:

我們同樣可以通過改變x軸的位置讓同一幅圖中顯示多個條形圖

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="10")

x_ticks = ["猩球崛起3:終極之戰(zhàn)", "敦刻爾克", "蜘蛛俠:英雄歸來", "戰(zhàn)狼2"]
bar_width = 0.2

x1 = range(len(x_ticks))
x2 = [i + bar_width for i in x1]
x3 = [i + bar_width * 2 for i in x1]
x = list(x1) + x2 + x3
b1 = [2358, 399, 2358, 362]
b2 = [12357, 156, 2045, 168]
b3 = [15746, 312, 4497, 319]

plt.figure(figsize=(15, 10))
plt.xticks(x2, x_ticks)

plt.xlabel("電影名稱")
plt.ylabel("票房:億元")
plt.title("幾部電影連續(xù)幾天票房的對比情況", weight="bold", size="16")

plt.bar(x1, b1, bar_width, label="第一天")
plt.bar(x2, b2, bar_width, label="第二天")
plt.bar(x3, b3, bar_width, label="第三天")
plt.legend()
plt.show()

代碼這里還有地方值得分析一下策菜。為什么使用x1,x2酒贬,x3就可以做到這樣的效果又憨?在本代碼中,x1 = [0, 1, 2, 3]锭吨,x2 = [0.2, 1.2, 2.2, 3.2]蠢莺,x3 = [0.4, 1.4, 2.4, 3.4],由于每一條的寬度統(tǒng)一設(shè)置為0.2耐齐,意味著第一條的中點在0浪秘,在[-0.1, 0.1]的范圍,第二條是以0.2為中點埠况,在[0.1, 0.3]的范圍內(nèi),第三條是以0.4為中點棵癣,在[0.3, 0.5]的范圍內(nèi)辕翰,這樣我們就發(fā)現(xiàn)每一組的三條是緊挨在一起的。

第二個問題就是狈谊,三個plt.bar()代碼分別畫的是哪一部分呢喜命?這個應(yīng)該好理解,三條命令分別畫的是藍色河劝、橙色和綠色壁榕,也就是說緊挨在一起的三條并不是同一條代碼畫出來的,而是先畫每一組的第一條赎瞎,再第二條牌里,最后第三條。

效果:

多個條形圖

(4)直方圖

plt.hist(x, bins)  # 頻數(shù)直方圖
plt.hist(x, bins, density=True)  # 頻率直方圖

案例:

畫出對250部電影時長分析的直方圖

a = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124, 101, 110, 116, 117, 110, 128, 128, 115, 99, 136, 126, 134, 95, 138, 117, 111,78, 132, 124, 113, 150, 110, 117, 86, 95, 144, 105, 126, 130,126, 130, 126, 116, 123, 106, 112, 138, 123, 86, 101, 99, 136,123, 117, 119, 105, 137, 123, 128, 125, 104, 109, 134, 125, 127,105, 120, 107, 129, 116, 108, 132, 103, 136, 118, 102, 120, 114,105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134,156, 106, 117, 127, 144, 139, 139, 119, 140, 83, 110, 102,123,107, 143, 115, 136, 118, 139, 123, 112, 118, 125, 109, 119, 133,112, 114, 122, 109, 106, 123, 116, 131, 127, 115, 118, 112, 135,115, 146, 137, 116, 103, 144, 83, 123, 111, 110, 111, 100, 154,136, 100, 118, 119, 133, 134, 106, 129, 126, 110, 111, 109, 141,120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126,114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137, 92,121, 112, 146, 97, 137, 105, 98, 117, 112, 81, 97, 139, 113,134, 106, 144, 110, 137, 137, 111, 104, 117, 100, 111, 101, 110,105, 129, 137, 112, 120, 113, 133, 112, 83, 94, 146, 133, 101,131, 116, 111, 84, 137, 115, 122, 106, 144, 109, 123, 116, 111,111, 133, 150]

分析:

直方圖中涉及到一個組數(shù)的概念,組數(shù) = 極差/組距牡辽,且最好是整除得到的組數(shù)喳篇。

代碼:

from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc("font", family='Source Han Sans CN', weight="regular", size="10")

a = [
    131, 98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107,
    114, 119, 128, 121, 142, 127, 130, 124, 101, 110, 116, 117, 110, 128, 128,
    115, 99, 136, 126, 134, 95, 138, 117, 111, 78, 132, 124, 113, 150, 110,
    117, 86, 95, 144, 105, 126, 130, 126, 130, 126, 116, 123, 106, 112, 138,
    123, 86, 101, 99, 136, 123, 117, 119, 105, 137, 123, 128, 125, 104, 109,
    134, 125, 127, 105, 120, 107, 129, 116, 108, 132, 103, 136, 118, 102, 120,
    114, 105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134, 156,
    106, 117, 127, 144, 139, 139, 119, 140, 83, 110, 102, 123, 107, 143, 115,
    136, 118, 139, 123, 112, 118, 125, 109, 119, 133, 112, 114, 122, 109, 106,
    123, 116, 131, 127, 115, 118, 112, 135, 115, 146, 137, 116, 103, 144, 83,
    123, 111, 110, 111, 100, 154, 136, 100, 118, 119, 133, 134, 106, 129, 126,
    110, 111, 109, 141, 120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114,
    125, 126, 114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137, 92,
    121, 112, 146, 97, 137, 105, 98, 117, 112, 81, 97, 139, 113, 134, 106, 144,
    110, 137, 137, 111, 104, 117, 100, 111, 101, 110, 105, 129, 137, 112, 120,
    113, 133, 112, 83, 94, 146, 133, 101, 131, 116, 111, 84, 137, 115, 122,
    106, 144, 109, 123, 116, 111, 111, 133, 150
]
d = 6  # 組距
bins = (max(a) - min(a)) // d  # 組數(shù)

plt.figure(figsize=(15, 10))
plt.grid()

plt.xlabel("時長")
plt.ylabel("數(shù)量")
plt.title("250部電影時長分析的直方圖", weight="bold", size="16")
plt.xticks(range(min(a), max(a) + d, d))

plt.hist(a, bins)  # 頻數(shù)直方圖
plt.show()

效果:

頻數(shù)直方圖

(5)其他

更多圖表見官網(wǎng):https://matplotlib.org/gallery/index.html

numpy部分

numpy主要用于處理數(shù)值型數(shù)據(jù)。

(1)使用numpy生成數(shù)組

import numpy as np

a = np.array([1, 2, 3, 4, 5])
b = np.array(range[1, 6])
c = np.arange((1, 6))

上面的a态辛,b麸澜,c的值是一樣的,都是一個類型為numpy.ndarray的數(shù)組[1 2 3 4 5]奏黑。

(2)數(shù)組的形狀

import numpy as np

t1 = np.arange(12)
t2 = np.array([[1, 2, 3], [4, 5, 6]])
>>> t1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])

>>> t2
array([[1, 2, 3],
       [4, 5, 6]])

查看數(shù)組的形狀:

>>> t1.shape
(12,)

>>> t2.shape
(2, 3)

shape屬性返回的是一個元組炊邦,說明了當前數(shù)組的形狀∈焓罚可以看出:

  • 元組的元素個數(shù)表示了數(shù)組的維數(shù)
  • 元組的第一個元素表示第一層數(shù)組所含元素個數(shù)馁害,第二個元素表示第二層數(shù)組所含元素個數(shù),以此類推
  • 當數(shù)組為二維時以故,第一個元素即為行數(shù)蜗细,第二個元素即為列數(shù)

修改數(shù)組的形狀

>>> t1.reshape((3, 4))  # 將t1變成一個3行4列的數(shù)組
array([[0, 1, 2, 3],
       [4, 5, 6, 7],
       [8, 9, 10, 11]])

>>> t1.reshape((3, 5))  # 試圖將t1變成一個3行5列的數(shù)組
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot reshape array of size 12 into shape (3,5)

可以看出,reshape方法傳遞一個表示維數(shù)的元組怒详,就會返回一個按要求修改的新數(shù)組炉媒,而不改變原數(shù)組。如果無法修改昆烁,則會報錯吊骤。

除了將低維數(shù)組變成高維,還可以降維:

>>> t2.reshape((6,))
array([1, 2, 3, 4, 5, 6])

>>> t2.flatten()
array([1, 2, 3, 4, 5, 6])

降維除了使用reshape静尼,如果直接降成一維白粉,可以使用flatten方法。

(3)數(shù)組的計算

數(shù)組與數(shù)字計算:

與數(shù)字進行計算時鼠渺,會把計算應(yīng)用到數(shù)組中的每一個元素鸭巴,這被稱為“廣播機制”。

數(shù)組與同維度數(shù)組計算:

與同維度數(shù)組進行計算時拦盹,會讓每一個對應(yīng)的元素進行計算鹃祖。

數(shù)組與不同維度的數(shù)組進行計算:

>>> t3 = np.arange(12).reshape((3, 4))
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> t4 = np.arange(3).reshape((3, 1))
array([[0],
       [1],
       [2]])
S
>>> t5 = np.arange(4)
array([0, 1, 2, 3])

>>> t3 + t4
array([[ 0,  1,  2,  3],
       [ 5,  6,  7,  8],
       [10, 11, 12, 13]])

>>> t3 + t5
array([[ 0,  2,  4,  6],
       [ 4,  6,  8, 10],
       [ 8, 10, 12, 14]])

可以看到,盡管兩個數(shù)組的維數(shù)不同普舆,但如果在橫向上維度相同恬口,則在橫向上進行運算,如果在豎向上維度相同沼侣,則在豎向上進行運算祖能。

事實上廣播原則并不局限于與數(shù)字計算時。如果兩個不同維度的數(shù)組沒有1維的方面蛾洛,兩個數(shù)組仍然是可以計算的养铸。例如:a = (3,3,2)可以和b = (3揭厚,2)進行運算却特,而不能和c = (3,3)進行運算筛圆。因為a中有三個(3裂明,2)的數(shù)組,可以使用廣播機制太援,而a中沒有(3闽晦,3)的數(shù)組,無法運算提岔。

(4)numpy讀取文件

數(shù)據(jù)分析中仙蛉,一般使用的是csv文件,即逗號分隔值文件碱蒙。

np.loadtxt(frame, dtype=np.float, delimiter=None, skiprows=0, usecols=None, unpack=False)
參數(shù) 解釋
frame 文件荠瘪、字符串或產(chǎn)生器,可以是gz或bz2壓縮文件
dtype 數(shù)據(jù)類型赛惩,可選哀墓,默認為np.float
delimiter 分隔字符串,默認是任何空格喷兼,若讀取csv文件則改為逗號
skiprows 跳過前x行
usecols 讀取指定的列篮绰,傳入列索引的元組
unpack 如果為True,則對源文件數(shù)據(jù)轉(zhuǎn)置季惯,如果為False吠各,則保持原文件數(shù)據(jù)不變

(5)numpy中的轉(zhuǎn)置

t.transpose()
t.T
t.swapaxis(1, 0)

以上三種方法都可以實現(xiàn)二位數(shù)組t的轉(zhuǎn)置。

(6)numpy的索引和切片

# 取行
t[2]

# 取連續(xù)的多行
t[2:5]

# 取不連續(xù)的多行
t[[2, 8, 10]]

# 取列
t[:, 2]

# 取連續(xù)的多列
t[:, 2:5]

# 取不連續(xù)的多列
t[:, [2, 8, 10]]

# 同時取行和列
t[3, 4]

# 取多行和多列(3-5行勉抓,2-4列)
t[2:5, 1:4]

# 取多個不相鄰的點
t[[0, 2, 5], [2, 4, 8]]

(7)numpy中的布爾索引

>>> t = np.arange(24).reshape((4, 6))
>>> t < 10
array([[ True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True, False, False],
       [False, False, False, False, False, False],
       [False, False, False, False, False, False]])

>>> t[t < 10] = 3
array([[ 3,  3,  3,  3,  3,  3],
       [ 3,  3,  3,  3, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

>>> t[t > 20]
array([21, 22, 23])

還可以通過whereclip三元運算符進行修改贾漏。

>>> t
array([[ 3,  3,  3,  3,  3,  3],
       [ 3,  3,  3,  3, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

>>> np.where(t<=3, 0, 100)  # t小于等于3的元素替換為0,否則替換為100
array([[  0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0, 100, 100],
       [100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100]])

>>> t.clip(10, 18)  # t中小于10的替換為10藕筋,大于18的替換為18
array([[10, 10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 18, 18, 18, 18, 18]])

值得注意的是whereclip都會返回一個新數(shù)組磕瓷,而不修改原來的數(shù)組。

(8)數(shù)組的拼接

>>> t1 = np.arange(12).reshape((2, 6))
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])

>>> t2 = np.arange(12, 24).reshape((2, 6))
array([[12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

>>> np.vstack((t1, t2))  # 豎直拼接
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

>>> np.hstack((t1, t2))  # 水平拼接
array([[ 0,  1,  2,  3,  4,  5, 12, 13, 14, 15, 16, 17],
       [ 6,  7,  8,  9, 10, 11, 18, 19, 20, 21, 22, 23]])

(9)數(shù)組的行列交換

>>> t = np.arange(12, 24).reshape((3, 4))
array([[12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

>>> t[[1, 2],:] = t[[2, 1],:]  # 行交換
array([[12, 13, 14, 15],
       [20, 21, 22, 23],
       [16, 17, 18, 19]])

>>> t[:, [0, 2]] = t[:, [2, 0]]  # 列交換
array([[14, 13, 12, 15],
       [22, 21, 20, 23],
       [18, 17, 16, 19]])

(10)numpy中的軸

軸(axis)使用0念逞,1,2边翁,……等數(shù)字進行表示翎承。在一個形狀為(2,)的一維數(shù)組中符匾,只有0軸叨咖,長度為2;在形狀為(2,3)的二維數(shù)組中甸各,有0軸和1軸垛贤,0軸長度為2,1軸長度為3趣倾,等等聘惦。

(11)numpy中的nan和inf

nan(Not a Number):不是一個數(shù)字。

在以下情況可能出現(xiàn)nan:

  • 讀取本地文件為float格式儒恋,如果有缺失善绎,則顯示nan
  • 做了不合適的運算,例如0 / 0 或inf - inf

關(guān)于nan诫尽,需要注意的有:

  • type(np.nan)為float類型
  • np.nan == np.nan返回False禀酱,np.nan != np.nan返回True
  • nan和任何值計算都是nan
  • 可以使用np.isnan(t)判斷一個數(shù)是不是nan或一個數(shù)組中是否含有nan
  • 可以使用np.count_nonzero(t!=t)np.count_nonzero(np.isnan(t))計算數(shù)組中nan的個數(shù)

inf(infinity):無窮大牧嫉,分為+inf和-inf剂跟。

在以下情況可能出現(xiàn)inf:

  • 一個數(shù)字除以0

nan和inf都是float類型

(12)numpy中的常用統(tǒng)計函數(shù)

方法 說明
t.sum(axis=None) 求和
t.mean(axis=None) 平均值
np.median(t, axis=None) 中位數(shù)
t.max(axis=None) 最大值
t.mim(axis=None) 最小值
np.ptp(t, axis=None) 極差
t.std(axis=None) 標準差

(13)其他方法

方法 說明
t.astype(int) 修改數(shù)組t的數(shù)據(jù)類型
np.argmax(t, axis=0) 獲取數(shù)組t在0軸上的最大值的位置
np.argmin(t, axis=1) 獲取數(shù)組t在1軸上的最小值的位置
np.zeros((3, 4)) 創(chuàng)建一個全0的數(shù)組
np.ones((3, 4)) 創(chuàng)建一個全1的數(shù)組
np.eye(3) 創(chuàng)建一個三階單位矩陣

pandas部分

pandas主要用于處理字符串數(shù)據(jù)。

pandas的常用數(shù)據(jù)類型:

  • Series:一維酣藻,帶標簽數(shù)組
  • DataFrame:二維曹洽,Series容器

(1)創(chuàng)建Series

import pandas as pd
import numpy as np

# 通過列表創(chuàng)建Series
t1 = pd.Series([1, 2, 3, 4, 5], index=list("abcde"))

# 通過字典創(chuàng)建Series
t2 = pd.Series({"name": "zhangsan", "age": 18, "tel": 10086})

# 通過numpy數(shù)組創(chuàng)建Series
t3 = pd.Series(np.arange(5))

如果不指定index,則默認是0臊恋,1衣洁,2,…抖仅。如果是字典類型創(chuàng)建的坊夫,則index為字典的key。

>>> t2
name    zhangsan
age           18
tel        10086
dtype: object

>>> t3
0    0
1    1
2    2
3    3
4    4
dtype: int64

>>> type(t2)
<class 'pandas.core.series.Series'>

>>> 0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
dtype: float64

Series有兩個屬性撤卢,分別是indexvalues环凿,可以獲取到一個Series的索引和值。

>>> t2.index
Index(['name', 'age', 'tel'], dtype='object')

>>> t2.values
array(['zhangsan', 18, 10086], dtype=object)

(2)Series的切片和索引

>>> t2["age"]
18

>>> t2[0]
'zhangsan'

>>> t2[1:]
age       18
tel    10086
dtype: object

>>> t2[[0, 2]]
name    zhangsan
tel        10086
dtype: object

>>> t3[t3>=3]
3    3
4    4
dtype: int64

(3)創(chuàng)建DataFrame

>>> t1 = pd.DataFrame(np.arange(12).reshape((3, 4)))
>>> t1
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

>>> t1 = pd.DataFrame(np.arange(12).reshape((3, 4)), index=list("abc"), columns=list("WXYZ"))
>>> t1
   W  X   Y   Z
a  0  1   2   3
b  4  5   6   7
c  8  9  10  11

>>> t2 = pd.DataFrame({"name": ["zhangsan", "lisi"], "age": [18, 22], "tel": [10086, 10000]})
>>> t2
       name  age    tel
0  zhangsan   18  10086
1      lisi   22  10000

>>> t3 = pd.DataFrame([{"name": "zhangsan", "age": 18, "tel": 10086}, {"name": "lisi", "age": 18}])
>>> t3
       name  age      tel
0  zhangsan   18  10086.0
1      lisi   18      NaN

可以看到3*4的矩陣外面多出來一列和一行放吩,豎著的一列叫index智听,即行索引,axis=0渡紫;橫著的一行叫columns到推,即列索引,axis=1惕澎。

創(chuàng)建DataFrame時莉测,可以傳入一個每個元素是列表的字典,也可以傳入一個每個元素是字典的列表唧喉,兩者相同捣卤。且沒有對應(yīng)索引的值處顯示NaN忍抽。

(4)DataFrame的描述信息

>>> t3.index
RangeIndex(start=0, stop=2, step=1)

>>> t3.columns
Index(['name', 'age', 'tel'], dtype='object')

>>> t3.values
array([['zhangsan', 18, 10086.0],
       ['lisi', 18, nan]], dtype=object)

>>> t3.shape
(2, 3)

>>> t3.dtypes
name     object
age       int64
tel     float64
dtype: object
    
>>> t3.ndim  # 顯示數(shù)據(jù)維度
2

除此之外,還有:

方法 說明
df.head(n) 顯示頭部幾行董朝,默認5行
df.tail(n) 顯示尾部幾行鸠项,默認5行
df.info() 顯示行數(shù)、列數(shù)子姜、列索引祟绊、列非空值個數(shù)、列類型闲询、內(nèi)存占用
df.describe() 計數(shù)久免、均值、標準差扭弧、最大值阎姥、四分位數(shù)、最小值
df.sort_values(by="", ascending=False) 按照by進行排序鸽捻,ascending默認為True呼巴,即升序

(5)DataFrame的索引

df[:]  # 取行,結(jié)果為DataFrame類型
df[""]  # 取列御蒲,結(jié)果為Series類型

df[:100]  # 取前100行
df["count_AnimalName"]  # 取count_AnimalName列
df[20:100]["count_AnimalName"]  # 取20-100行的count_AnimalName列

當然還有其他的方法:loc和iloc:

loc:通過標簽獲取數(shù)據(jù)

>>> t
   W  X   Y   Z
a  0  1   2   3
b  4  5   6   7
c  8  9  10  11

>>> t.loc["a", "W"]
0

>>> t.loc["a", ["W", "Z"]]
W    0
Z    3
Name: a, dtype: int64

>>> t.loc["a":"c", ["W", "Z"]]
   W   Z
a  0   3
b  4   7
c  8  11

iloc:通過位置獲取數(shù)據(jù)

>>> t.iloc[:1, [0, 2]]
   W  Y
a  0  2

>>> t.iloc[:, 2]
a     2
b     6
c    10
Name: Y, dtype: int64

(6)pandas的布爾索引

>>> t[t["X"]>4]
   W  X   Y   Z
b  4  5   6   7
c  8  9  10  11

>>> t[(t["W"]>0) & (t["Z"]<8)]
   W  X  Y  Z
b  4  5  6  7

(7)pandas的字符串方法

pandas有許多字符串操作方法衣赶,例如我想取出Row_Labels列中字符串長度大于4的行,可以:

df[df["Row_Labels"].str.len() > 4]

通過df.str.方法()的方式進行調(diào)用厚满。具體方法列表此處不展開府瞄。

(8)pandas缺失數(shù)據(jù)的處理

先來看這樣一組數(shù)據(jù):

>>> t
      U     V     W     X     Y     Z
A   NaN   1.0   2.0   3.0   4.0   NaN
B   6.0   7.0   8.0   9.0   0.0  11.0
C  12.0  13.0  14.0  15.0  16.0  17.0
D  18.0  19.0   NaN  21.0  22.0  23.0

數(shù)據(jù)缺失一般有兩種情況,一種是NaN(即np.nan)碘箍,一種是0遵馆。

判斷數(shù)據(jù)是否為nan:

>>> pd.isnull(t)
       U      V      W      X      Y      Z
A   True  False  False  False  False   True
B  False  False  False  False  False  False
C  False  False  False  False  False  False
D  False  False   True  False  False  False

>>> pd.notnull(t)
       U     V      W     X     Y      Z
A  False  True   True  True  True  False
B   True  True   True  True  True   True
C   True  True   True  True  True   True
D   True  True  False  True  True   True

nan處理方法:

方法一:選出不含nan的行列

>>> t1 = t[pd.notnull(t["U"])]
>>> t1
      U     V     W     X     Y     Z
B   6.0   7.0   8.0   9.0   0.0  11.0
C  12.0  13.0  14.0  15.0  16.0  17.0
D  18.0  19.0   NaN  21.0  22.0  23.0

方法二:刪除含有nan的行列

df.dropna(axis=0, how="any", inplace=False)

axis指定操作的軸;how默認為any丰榴,即一整行只要包含nan就刪除货邓,可以改成all,表示只有一整行全都是nan才刪除四濒;inplace表示是否將結(jié)果直接賦給原變量换况,默認為False。

>>> t.dropna(how="any")
      U     V     W     X     Y     Z
B   6.0   7.0   8.0   9.0   0.0  11.0
C  12.0  13.0  14.0  15.0  16.0  17.0

方法三:用值填充nan

df.fillna(value)

一般可以使用均值盗蟆、中位數(shù)和0填充nan戈二。

>>> t.fillna(t.mean())
      U     V     W     X     Y     Z
A  12.0   1.0   2.0   3.0   4.0  17.0
B   6.0   7.0   8.0   9.0   0.0  11.0
C  12.0  13.0  14.0  15.0  16.0  17.0
D  18.0  19.0   8.0  21.0  22.0  23.0

我們會發(fā)現(xiàn),對含有nan的列計算平均值時喳资,會自動忽略nan挽拂,計算余下值的平均值。這與numpy中不同骨饿,在numpy中亏栈,nan與任何值運算都是nan。

0值處理方法:

對于不需要處理的0(比如實際值就是0)我們可以不處理宏赘;對于需要處理的0绒北,可以統(tǒng)一賦值為nan:

t[t==0] = np.nan

需要注意的是,0會參與均值和中位數(shù)的運算察署。

(9)數(shù)據(jù)合并

join:把行索引相同的數(shù)據(jù)合并到一起

>>> t1 = pd.DataFrame(np.zeros((2, 5)), index=list("AB"), columns=list("VWXYZ"))
>>> t1
     V    W    X    Y    Z
A  0.0  0.0  0.0  0.0  0.0
B  0.0  0.0  0.0  0.0  0.0

>>> t2 = pd.DataFrame(np.ones((3, 4)), index=list("ABC"))
>>> t2
     0    1    2    3
A  1.0  1.0  1.0  1.0
B  1.0  1.0  1.0  1.0
C  1.0  1.0  1.0  1.0

>>> t2.join(t1)
     0    1    2    3    V    W    X    Y    Z
A  1.0  1.0  1.0  1.0  0.0  0.0  0.0  0.0  0.0
B  1.0  1.0  1.0  1.0  0.0  0.0  0.0  0.0  0.0
C  1.0  1.0  1.0  1.0  NaN  NaN  NaN  NaN  NaN

>>> t1.join(t2)
     V    W    X    Y    Z    0    1    2    3
A  0.0  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
B  0.0  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0

可以發(fā)現(xiàn)闷游,當t2.join(t1)時,t1的AB行內(nèi)容直接增加在后面贴汪,新增了VWXYZ列脐往,而空缺的C行全為NaN。當t1.join(t2)時扳埂,t2的C行直接被刪去了业簿。故誰調(diào)用join方法,就以誰為基礎(chǔ)阳懂。

merge:按照指定的列把數(shù)據(jù)按照一定方式合并到一起

首先我們定義兩個新的數(shù)據(jù):

>>> df1 = pd.DataFrame(np.ones((2, 4)), index=list("AB"), columns=list("abcd"))
>>> df2 = pd.DataFrame(np.arange((3, 3)), columns=list("fax"))

>>> df1
     a    b    c    d
A  1.0  1.0  1.0  1.0
B  1.0  1.0  1.0  1.0

>>> df2
   f  a  x
0  0  1  2
1  3  4  5
2  6  7  8

然后執(zhí)行下面的命令:

>>> df1.merge(df2, on="a", how="inner")
     a    b    c    d  f  x
0  1.0  1.0  1.0  1.0  0  2
1  1.0  1.0  1.0  1.0  0  2

我們把df2合并到df1中梅尤,并指定參數(shù)on為a,意思是按照a列進行合并岩调,參數(shù)how的值為inner巷燥,表示取交集,inner亦為該參數(shù)的默認值号枕。

df1中a列全為1缰揪,df2中只有0行為1,1行和2行與df1并無交集葱淳,所以df2中0行的f和x列均被合并至df1中的0行和1行钝腺。

如果將df2的[1, "a"]處修改為1,再執(zhí)行該代碼蛙紫,結(jié)果如下:

>>> df2.loc[1, "a"] = 1
>>> df2
   f  a  x
0  0  1  2
1  3  1  5
2  6  7  8

>>> df1.merge(df2, on="a")
     a    b    c    d  f  x
0  1.0  1.0  1.0  1.0  0  2
1  1.0  1.0  1.0  1.0  3  5
2  1.0  1.0  1.0  1.0  0  2
3  1.0  1.0  1.0  1.0  3  5

可以看到拍屑,df2的a列中有兩個1,分別是0行和1行坑傅,合并后的結(jié)果共有四行僵驰,分別是把df2的0行和1行合并至df1的0行,再把df2的0行和1行合并至df1的1行唁毒。

下面是how為outer的情況蒜茴,outer表示取并集:

>>> df1.loc["A", "a"] = 100
>>> df1
       a    b    c    d
A  100.0  1.0  1.0  1.0
B    1.0  1.0  1.0  1.0
>>> df2
   f  a  x
0  0  1  2
1  3  1  5
2  6  7  8

>>> df1.merge(df2, on="a", how="outer")
       a    b    c    d    f    x
0  100.0  1.0  1.0  1.0  NaN  NaN
1    1.0  1.0  1.0  1.0  0.0  2.0
2    1.0  1.0  1.0  1.0  3.0  5.0
3    7.0  NaN  NaN  NaN  6.0  8.0

我們會發(fā)現(xiàn),在合并后的第0行浆西,df1的a是100粉私,而df2中沒有a為100的行,故以df1為準近零,空缺位置補NaN诺核。1行和2行與上面的例子相同抄肖,不再解釋。由于df1僅有2行窖杀,又此處是outer漓摩,故3行以df2為主,df1空缺處補NaN入客。

還有左連接和右連接管毙,分別對應(yīng)left和right,結(jié)果如下:

>>> df1.merge(df2, on="a", how="left")
       a    b    c    d    f    x
0  100.0  1.0  1.0  1.0  NaN  NaN
1    1.0  1.0  1.0  1.0  0.0  2.0
2    1.0  1.0  1.0  1.0  3.0  5.0

>>> df1.merge(df2, on="a", how="right")
     a    b    c    d  f  x
0  1.0  1.0  1.0  1.0  0  2
1  1.0  1.0  1.0  1.0  3  5
2  7.0  NaN  NaN  NaN  6  8

這兩種模式可以理解為outer的細分桌硫,left就是在outer的基礎(chǔ)上完全以df1為準夭咬,故在outer的結(jié)果上刪除了3行。right就是在outer的基礎(chǔ)上完全以df2為準铆隘,所以[0, "a"]位置上的值是1而不是100卓舵。

除了直接指定on,還可以分別指定left_on和right_on咖驮,例如:

>>> df1.merge(df2, left_on="a", right_on="f")
Empty DataFrame
Columns: [a_x, b, c, d, f, a_y, x]
Index: []

可以看到返回了一個空結(jié)果边器,因為df1的a列和df2的f列并無交集。

(10)數(shù)據(jù)分組聚合

有時候我們有一組龐大的數(shù)據(jù)托修,需要對數(shù)據(jù)進行分組研究(比如按國家忘巧,按性別等等),可以使用分組聚合睦刃。

df = pd.read_csv(file_path)
grouped = df.groupby(by="Country")  # 按country字段進行分組

grouped是一個DataFrameGroupBy類型的對象砚嘴,可以進行遍歷或調(diào)用聚合方法。

遍歷:

for i in grouped:
    print(i)

for i, j in grouped:
    print(i)
    print(j)

每一個i是一個元組涩拙,第一個元素是Country的值际长,第二個元素是一個DataFrame,保存了該Country下的所有其他列的信息兴泥。也可以用下面的方法分別遍歷第一個元素和第二個元素工育。

分組之后,可以調(diào)用許多聚合方法:

print(grouped.count())  # 統(tǒng)計每個國家的其他所有列總數(shù)
print(grouped["Brands"].count())  # 統(tǒng)計每個國家的Brands總數(shù)

除此之外搓彻,還有平均值如绸、中位數(shù)等聚合方法。

方法 說明
count 非NaN值的數(shù)量
sum 非NaN值的和
mean 非NaN值的平均數(shù)
median 非NaN值的算數(shù)中位數(shù)
std旭贬、var 無偏(分母為n-1)標準差和方差
min怔接、max 非NaN值的最小值和最大值

還可以按照多個條件進行分組:

# 分別按照國家和省份進行分組,返回Series
grouped = df.groupby(by=["Country", "State/Province"])   

# 分別按照國家和省份進行分組稀轨,并只取Brand列數(shù)據(jù)扼脐,返回Series
grouped = df["Brand"].groupby(by=[df["Country"], df["State/Province"]])
grouped = df.groupby(by=["Country", "State/Province"])["Brand"]

# 分別按照國家和省份進行分組,并只取Brand列數(shù)據(jù)奋刽,返回DataFrame
grouped = df[["Brand"]].groupby(by=[df["Country"], df["State/Province"]])   
grouped = df.groupby(by=["Country", "State/Province"])[["Brand"]]

上面的例子中瓦侮,如果返回的是Series艰赞,輸出之后會發(fā)現(xiàn)仍然有三行,但卻是Series類型脏榆。前兩列都是索引猖毫,被稱為復合索引。

(11)復合索引

簡單的索引操作:

  • 獲取索引:df.index
  • 指定索引:df.index = ["x", "y"]
  • 重新設(shè)置索引:df.reindex(list("abcd"))须喂,類似于從df中取出索引為a、b趁蕊、c坞生、d的四行,如果不存在則全為NaN
  • 指定某一列作為索引:df.set_index("Country", drop=False)掷伙,drop為False表示在df中仍然保留Country列的內(nèi)容
  • 返回索引的唯一值:df.index.unique()是己,索引可以重復,unique()方法同樣適用于索引

但假如我使用df.set_index(["a", "b"])會怎樣呢任柜?

>>> df = pd.DataFrame(np.arange(12).reshape((3, 4)), columns=list("abcd"))
>>> df
   a  b   c   d
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

>>> df1 = df.set_index(["a", "b"])
>>> df1
      c   d
a b        
0 1   2   3
4 5   6   7
8 9  10  11

>>> df1.index
MultiIndex([(0, 1),
            (4, 5),
            (8, 9)],
           names=['a', 'b'])

我們會發(fā)現(xiàn)df1中有兩個索引卒废,分別是a和b,這就是復合索引宙地。

對于Series的復合索引摔认,可以使用t["a", "b"]的方式來取值,對于DataFrame的復合索引宅粥,可以使用df.loc["a"].loc["b"]的方式來取值参袱。如果我們希望先取第二層索引,再取第一層索引秽梅,可以通過df.swaplevel()交換索引次序抹蚀。

(12)pandas的時間序列

pd.date_range(start=None, end=None, periods=None, freq="D")

其中:

  • start:開始時間
  • end:結(jié)束時間
  • periods:重復次數(shù)
  • freq:頻率

我們來看幾個例子:

>>> pd.date_range(start="20200601", end="20200701", freq="D")
DatetimeIndex(['2020-06-01', '2020-06-02', '2020-06-03', '2020-06-04',
               '2020-06-05', '2020-06-06', '2020-06-07', '2020-06-08',
               '2020-06-09', '2020-06-10', '2020-06-11', '2020-06-12',
               '2020-06-13', '2020-06-14', '2020-06-15', '2020-06-16',
               '2020-06-17', '2020-06-18', '2020-06-19', '2020-06-20',
               '2020-06-21', '2020-06-22', '2020-06-23', '2020-06-24',
               '2020-06-25', '2020-06-26', '2020-06-27', '2020-06-28',
               '2020-06-29', '2020-06-30', '2020-07-01'],
              dtype='datetime64[ns]', freq='D')

>>> pd.date_range(start="20200601", end="20200701", freq="10D")
DatetimeIndex(['2020-06-01', '2020-06-11', '2020-06-21', '2020-07-01'], dtype='datetime64[ns]', freq='10D')

>>> pd.date_range(start="20200601", periods=10, freq="M")
DatetimeIndex(['2020-06-30', '2020-07-31', '2020-08-31', '2020-09-30',
               '2020-10-31', '2020-11-30', '2020-12-31', '2021-01-31',
               '2021-02-28', '2021-03-31'],
              dtype='datetime64[ns]', freq='M')

關(guān)于頻率的更多縮寫:

別名 說明
D 每日歷日
B 每工作日
H 每小時
T或min 每分
S 每秒
L或ms 每毫秒
U 每微秒
M 每月最后一個日歷日
BM 每月最后一個工作日
MS 每月第一個日歷日
BMS 每月第一個工作日

通過下面的命令,可以把時間字符串轉(zhuǎn)換為時間序列:

df["timeStamp"] = pd.to_datetime(df["timeStamp"], format="")

其中df["timpStamp"]中原本為時間字符串企垦,使用pd.to_datetime()可以轉(zhuǎn)化為時間索引环壤。format一般不用寫,除非時間格式特殊(比如包含中文)钞诡。

(13)重采樣

可以使用resample方法將時間序列從一個頻率轉(zhuǎn)化為另一個頻率郑现。注意該方法僅針對時間為索引的情況,如果時間不為索引臭增,可以用df.set_index("timeStamp")進行設(shè)置懂酱。

將高頻率數(shù)據(jù)轉(zhuǎn)化為低頻率數(shù)據(jù)稱為降采樣,將地頻率數(shù)據(jù)轉(zhuǎn)化為高頻率數(shù)據(jù)稱為升采樣誊抛。

例如:

t.resample("M").mean()  # 按月重采樣后計算每月平均值

t.reesample("10D").count()  # 按10天從采樣后計算每10天的總數(shù)

(14)對時間段的處理

在前面講到的DatetimeIndex可以理解為對時間戳的處理列牺,這一部分要說一下PeriodIndex,是對一個時間段的處理拗窃。如果數(shù)據(jù)中保存的時間不是一個完整的數(shù)據(jù)瞎领,而是分別存為了年泌辫、月、日九默,可以用下面的方法轉(zhuǎn)換為時間類型進行處理:

period = pd.PeriodIndex(year, month, day, hour, freq)

前四個參數(shù)傳入對應(yīng)的列震放,再根據(jù)freq參數(shù)生成一個時間段。

對于時間段的重采樣驼修,可以按下面的方法進行:

data = df.set_index(period).resample("10D")
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末殿遂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乙各,更是在濱河造成了極大的恐慌墨礁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耳峦,死亡現(xiàn)場離奇詭異恩静,居然都是意外死亡,警方通過查閱死者的電腦和手機蹲坷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門驶乾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人循签,你說我怎么就攤上這事级乐。” “怎么了懦底?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵唇牧,是天一觀的道長。 經(jīng)常有香客問我聚唐,道長丐重,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任杆查,我火速辦了婚禮扮惦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亲桦。我一直安慰自己崖蜜,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布客峭。 她就那樣靜靜地躺著豫领,像睡著了一般。 火紅的嫁衣襯著肌膚如雪舔琅。 梳的紋絲不亂的頭發(fā)上等恐,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音,去河邊找鬼课蔬。 笑死囱稽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的二跋。 我是一名探鬼主播战惊,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扎即!你這毒婦竟也來了吞获?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤谚鄙,失蹤者是張志新(化名)和其女友劉穎衫哥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體襟锐,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年膛锭,在試婚紗的時候發(fā)現(xiàn)自己被綠了粮坞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡初狰,死狀恐怖莫杈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奢入,我是刑警寧澤筝闹,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站腥光,受9級特大地震影響关顷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜武福,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一议双、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捉片,春花似錦平痰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莹规,卻和暖如春赔蒲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工嘹履, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腻扇,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓砾嫉,卻偏偏與公主長得像幼苛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子焕刮,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354