03 -1 pandas 中 DataFrame理解與建立、索引、運算的詳解以及例項
DataFrame
DataFrame是一個【表格型】的資料結構,可以看做是【由Series組成的字典】(共用同一個索引)。DataFrame由按一定順序排列的多列資料組成。設計初衷是將Series的使用場景從一維拓展到多維。DataFrame既有行索引,也有列索引。
- 行索引:index 代表樣本
- 列索引:columns 代表維度
- 值:values(numpy的二維陣列)
1)DataFrame的建立
最常用的方法是傳遞一個字典來建立。DataFrame以字典的鍵作為每一【列】的名稱,以字典的值(一個數組)作為每一列。
此外,DataFrame會自動加上每一行的索引(和Series一樣)。
同Series一樣,若傳入的列與字典的鍵不匹配,則相應的值為NaN。
DataFrame的建立
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
通過 DateFrame 函式 建立
df = DataFrame([1,2,3,4])
結果為:
0
0 1
1 2
2 3
3 4
df = DataFrame([1,2,3,4],index=list("abcd"))
結果為:
0
a 1
b 2
c 3
d 4
data = np.random.randint(0,150,size=(4,4)) index = ["張三","李四","王五","趙柳"] columns = ["Math","Chinese","English","Python"] df = DataFrame(data,index=index,columns=columns) df 結果為:如下表
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 10 | 145 | 15 | 11 |
李四 | 125 | 97 | 71 | 130 |
王五 | 149 | 79 | 149 | 67 |
趙柳 | 133 | 26 | 135 | 70 |
DataFrame屬性:values、columns、index、shape
df.values #所有的值
結果為:
array([[ 10, 145, 15, 11],
[125, 97, 71, 130],
[149, 79, 149, 67],
[133, 26, 135, 70]])
df.columns # 每一列的標題
結果為:
Index(['Math', 'Chinese', 'English', 'Python'], dtype='object')
df.index #每一行的標題
結果為:
Index(['張三', '李四', '王五', '趙柳'], dtype='object')
df.shape
結果為:
(4, 4)
============================================
練習4:
根據以下考試成績表,建立一個DataFrame,命名為df:
張三 李四
語文 150 0
數學 150 0
英語 150 0
理綜 300 0
============================================
data = [[150,0],[150,0],[150,0],[150,0]]
index = ["語文","數學","英語","理綜"]
columns = ["張三","李四"]
DataFrame(data=data,index=index,columns=columns)
張三 | 李四 | |
---|---|---|
語文 | 150 | 0 |
數學 | 150 | 0 |
英語 | 150 | 0 |
理綜 | 150 | 0 |
2)DataFrame的索引
(1) 對列進行索引
- 通過類似字典的方式
- 通過屬性的方式
可以將DataFrame的列獲取為一個Series。返回的Series擁有原DataFrame相同的索引,且name屬性也已經設定好了,就是相應的列名。
每一行是一個樣本 每一列是描述這個樣本的維度
df
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 10 | 145 | 15 | 11 |
李四 | 125 | 97 | 71 | 130 |
王五 | 149 | 79 | 149 | 67 |
趙柳 | 133 | 26 | 135 | 70 |
df["Math"] # 按照字典的方式去從DataFrame裡取資料
結果為
張三 10
李四 125
王五 149
趙柳 133
Name: Math, dtype: int32
type(df["Math"])
結果為:pandas.core.series.Series
df.Math
結果為:
張三 10
李四 125
王五 149
趙柳 133
Name: Math, dtype: int32
(2) 對行進行索引
- 使用.loc[]加index來進行行索引
- 使用.iloc[]加整數來進行行索引
同樣返回一個Series,index為原來的columns。
df["張三"] # columns才能以索引的方式去取 index不行
結果為:
KeyError: '張三'
df.loc["張三"]
結果為:
Math 10
Chinese 145
English 15
Python 11
Name: 張三, dtype: int32
df.iloc[0]
結果為:
Math 10
Chinese 145
English 15
Python 11
Name: 張三, dtype: int32
總結
columns 才能以索引的形式去找 df[“列名”] df.列名
index 不能用索引的方式去找 只能用 loc[] 和 iloc[] 去定位內容
(3) 對元素進行索引
- 使用列索引
- 使用行索引(iloc[3,1]相當於兩個引數;iloc[[3,3]] 裡面的[3,3]看做一個引數)
- 使用values屬性(二維numpy陣列)
df["Math"].loc["張三"] 結果為:10
df["Math"].iloc[0] 結果為:10
df.loc["張三"]
結果為:
Math 10
Chinese 145
English 15
Python 11
Name: 張三, dtype: int32
type(df.loc["張三"])
結果為:
pandas.core.series.Series
df.loc["張三"].loc["Math"]
結果為:10
DataFrame自帶的方式
loc是DataFrame提供的定位元素的方法 ,可以傳入行的名稱去查詢整行,也可以 先傳入行名稱 ,再傳入列名稱 去定位元素,但是不能直接把列的名稱放前面
df.loc["張三","Math"] 結果為:10
df.loc["Math","張三"] 此查詢方法錯誤
# 終極方式
df.values[0,0] 結果為:10
【注意】 直接用中括號時:
- 索引表示的是列索引
- 切片表示的是行切片
df
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 58 | 119 | 94 | 95 |
李四 | 31 | 7 | 42 | 124 |
王五 | 59 | 24 | 10 | 52 |
趙柳 | 24 | 2 | 88 | 3In [64]: |
df["Math"] #df後面跟中括號作為索引的話 只能傳入列名 對列進行索引
結果為:
張三 10
李四 125
王五 149
趙柳 133
Name: Math, dtype: int32
df[0:3] #df後面的中括號中 如果傳的是切片的方式 是對行進行切片
結果為:如下表
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 10 | 145 | 15 | 11 |
李四 | 125 | 97 | 71 | 130 |
王五 | 149 | 79 | 149 | 67 |
df["Math":"English"] # 如果想對列進行切片
結果如下表:
Math | Chinese | English | Python | |
---|---|---|---|---|
df.iloc[:,0:2] # 需要通過iloc才能對列進行切片
Math | Chinese | |
---|---|---|
張三 | 10 | 145 |
李四 | 125 | 97 |
王五 | 149 | 79 |
趙柳 | 133 | 26 |
============================================
練習5:
使用多種方法對df進行索引和切片,並比較其中的區別
============================================
3)DataFrame的運算
(1) DataFrame和數值的運算
df+1 # 所有內容都加一
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 11 | 146 | 16 | 12 |
李四 | 126 | 98 | 72 | 131 |
王五 | 150 | 80 | 150 | 68 |
趙柳 | 134 | 27 | 136 | 71 |
df["Python"] = df["Python"]+1 #兩種方法是一樣的效果,所以相當於加了兩次
df["Python"]+=1
df
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 10 | 145 | 15 | 14 |
李四 | 125 | 97 | 71 | 133 |
王五 | 149 | 79 | 149 | 70 |
趙柳 | 133 | 26 | 135 | 73 |
df["Python"]["張三"] +=1
df
Math | Chinese | English | Python | |
---|---|---|---|---|
張三 | 10 | 145 | 15 | 15 |
李四 | 125 | 97 | 71 | 133 |
王五 | 149 | 79 | 149 | 70 |
趙柳 | 133 | 26 | 135 | 73 |
(2) DataFrame與DataFrame之間的運算
同Series一樣:
- 在運算中自動對齊不同索引的資料
- 如果索引不對應,則補NaN
下面是Python 操作符與pandas操作函式的對應表:
Python Operator | Pandas Method(s) |
---|---|
+ |
add() |
- |
sub() , subtract() |
* |
mul() , multiply() |
/ |
truediv() , div() , divide() |
// |
floordiv() |
% |
mod() |
** |
pow() |
df1 = DataFrame(np.random.randint(0,150,size=(5,5)),
index=list("01234"),
columns=list("ABCDE"))
df2 = DataFrame(np.random.randint(0,150,size=(5,5)),
index=list("12345"),
columns=list("ABCDE"))
display(df1,df2)
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 105 | 143 | 70 | 148 | 25 |
1 | 21 | 130 | 78 | 51 | 38 |
2 | 2 | 15 | 146 | 39 | 115 |
3 | 20 | 139 | 58 | 90 | 11 |
4 | 35 | 56 | 64 | 101 | 19 |
A | B | C | D | E | |
---|---|---|---|---|---|
1 | 74 | 143 | 12 | 73 | 85 |
2 | 76 | 123 | 30 | 17 | 103 |
3 | 89 | 127 | 84 | 43 | 134 |
4 | 46 | 41 | 97 | 133 | 109 |
5 | 9 | 79 | 102 | 50 | 112 |
df1+df2 # 行和列索引名都對應 則 對應項相加
A | B | C | D | E | |
---|---|---|---|---|---|
0 | NaN | NaN | NaN | NaN | NaN |
1 | 95.0 | 273.0 | 90.0 | 124.0 | 123.0 |
2 | 78.0 | 138.0 | 176.0 | 56.0 | 218.0 |
3 | 109.0 | 266.0 | 142.0 | 133.0 | 145.0 |
4 | 81.0 | 97.0 | 161.0 | 234.0 | 128.0 |
5 | NaN | NaN | NaN | NaN | NaN |
(3) DataFrame和Series之間的運算
df1 = DataFrame(data=np.random.randint(0,150,size=(5,5)),index=list("ABCDE"),columns=list("01234"))
s1 = Series(data=np.random.randint(0,150,size=5),index=list("01234"))
s2 = Series(data=np.random.randint(0,150,size=5),index=list("ABCDE"))
df1
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 143 | 31 | 15 | 91 | 81 |
B | 8 | 64 | 78 | 57 | 9 |
C | 142 | 116 | 23 | 98 | 114 |
D | 30 | 113 | 39 | 86 | 113 |
E | 7 | 0 | 48 | 39 | 122 |
s1
結果為:
0 44
1 101
2 67
3 63
4 124
dtype: int32
df1+s1 #series的索引和DataFrame的列索引對應 則每一行對應項相加
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 114 | 175 | 230 | 192 | 126 |
B | 183 | 110 | 212 | 106 | 198 |
C | 86 | 142 | 162 | 88 | 167 |
D | 226 | 92 | 220 | 52 | 117 |
E | 198 | 56 | 223 | 56 | 232 |
s2
結果為:
A 7
B 64
C 56
D 141
E 88
dtype: int32
df1
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 143 | 31 | 15 | 91 | 81 |
B | 8 | 64 | 78 | 57 | 9 |
C | 142 | 116 | 23 | 98 | 114 |
D | 30 | 113 | 39 | 86 | 113 |
E | 7 | 0 | 48 | 39 | 122 |
df1+s2 #預設是 Series的索引和DataFrame的列索引去對應 然後相加
0 | 1 | 2 | 3 | 4 | A | B | C | D | E | |
---|---|---|---|---|---|---|---|---|---|---|
A | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
B | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
C | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
D | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
E | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
df1.add(s2,axis="index")
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 150 | 38 | 22 | 98 | 88 |
B | 72 | 128 | 142 | 121 | 73 |
C | 198 | 172 | 79 | 154 | 170 |
D | 171 | 254 | 180 | 227 | 254 |
E | 95 | 88 | 136 | 127 | 210 |
============================================
練習6:
- 假設df1是期中考試成績,df2是期末考試成績,請自由建立df1和df2,並將相加,求期中期末平均值。
- 假設張三期中考試數學被發現作弊,要記為0分,如何實現?
- 李四因為舉報張三作弊立功,期中考試所有科目加100分,如何實現?
- 後來老師發現有一道題出錯了,為了安撫學生情緒,給每位學生每個科目都加10分,如何實現?
============================================
In [103]:
index = ["張三","李四"]
columns = ["語文","數學","英語"]
data = np.random.randint(0,150,size=(2,3))
df1 = DataFrame(data,index=index,columns=columns)
df1
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 136 | 11 | 96 |
李四 | 39 | 52 | 91 |
index = ["張三","李四"]
columns = ["語文","數學","英語"]
data = np.random.randint(0,150,size=(2,3))
df2 = DataFrame(data,index=index,columns=columns)
df2
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 28 | 30 | 57 |
李四 | 27 | 5 | 20 |
(df1+df2)/2
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 82.0 | 20.5 | 76.5 |
李四 | 33.0 | 28.5 | 55.5 |
df1["數學"].loc["張三"] 結果為:11
df1.loc["張三"].loc["數學"]=0
df1
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 136 | 0 | 96 |
李四 | 39 | 52 | 91 |
df1.loc["李四"]+=100
df1
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 136 | 0 | 96 |
李四 | 139 | 152 | 191 |
df1+=10
df1
語文 | 數學 | 英語 | |
---|---|---|---|
張三 | 146 | 10 | 106 |
李四 | 149 | 162 | 201 |