注意:本文是根據(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é)果如下:
可以看到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é)果如下:
這樣一來押框,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()
顯示效果如下:
(3)增加網(wǎng)格
為了更加清楚的展示每個點的位置扁掸,我們可以為圖形添加網(wǎng)格:
plt.grid()
添加網(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()
最后效果如圖:
(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()
效果:
(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])
還可以通過where
和clip
三元運算符進行修改贾漏。
>>> 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]])
值得注意的是where
和clip
都會返回一個新數(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有兩個屬性撤卢,分別是index
和values
环凿,可以獲取到一個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")